From fcf11c70ab3341836406b6651984c9aa08f777b1 Mon Sep 17 00:00:00 2001 From: eyurtsev Date: Wed, 7 Feb 2024 13:40:17 +0000 Subject: [PATCH] deploy: 4d6a3fbb98d04fa714a9984a6dd4690b98689c3b --- .buildinfo | 4 + .doctrees/api.doctree | Bin 0 -> 28170 bytes .doctrees/apis.doctree | Bin 0 -> 48565 bytes .doctrees/document_extraction.doctree | Bin 0 -> 55693 bytes .doctrees/environment.pickle | Bin 0 -> 200897 bytes .doctrees/generated/kor.doctree | Bin 0 -> 864041 bytes .doctrees/generated/kor.documents.doctree | Bin 0 -> 19314 bytes .doctrees/generated/kor.encoders.doctree | Bin 0 -> 191177 bytes .doctrees/generated/kor.extraction.doctree | Bin 0 -> 192538 bytes .doctrees/generated/modules.doctree | Bin 0 -> 2683 bytes .doctrees/guidelines.doctree | Bin 0 -> 8020 bytes .doctrees/index.doctree | Bin 0 -> 21613 bytes .doctrees/nested_objects.doctree | Bin 0 -> 18391 bytes .doctrees/objects.doctree | Bin 0 -> 23170 bytes .doctrees/prompt.doctree | Bin 0 -> 14213 bytes .doctrees/schema_serialization.doctree | Bin 0 -> 18269 bytes .doctrees/tutorial.doctree | Bin 0 -> 21014 bytes .doctrees/type_descriptors.doctree | Bin 0 -> 18480 bytes .doctrees/untyped_objects.doctree | Bin 0 -> 11282 bytes .doctrees/validation.doctree | Bin 0 -> 50359 bytes .nojekyll | 0 _modules/index.html | 324 + _modules/kor/adapters.html | 539 + _modules/kor/documents/html.html | 391 + _modules/kor/documents/typedefs.html | 318 + _modules/kor/encoders/csv_data.html | 445 + _modules/kor/encoders/encode.html | 411 + _modules/kor/encoders/json_data.html | 416 + _modules/kor/encoders/typedefs.html | 357 + _modules/kor/encoders/utils.html | 326 + _modules/kor/encoders/xml.html | 474 + _modules/kor/examples.html | 427 + _modules/kor/exceptions.html | 316 + _modules/kor/extraction/api.html | 494 + _modules/kor/extraction/parser.html | 383 + _modules/kor/extraction/typedefs.html | 337 + _modules/kor/nodes.html | 598 + _modules/kor/prompts.html | 485 + _modules/kor/type_descriptors.html | 443 + _modules/kor/validators.html | 384 + ...strap.5fd3999ee7762ccc51105388f4a9d115.css | 1 + ...-main.c949a650a448cc0ae9fd3441c0e17fb0.css | 1 + ...ables.06eb56fa6e07937060861dad626602ad.css | 7 + _sources/api.rst.txt | 86 + _sources/apis.ipynb.txt | 858 ++ _sources/document_extraction.ipynb.txt | 1021 ++ _sources/generated/kor.documents.rst.txt | 29 + _sources/generated/kor.encoders.rst.txt | 61 + _sources/generated/kor.extraction.rst.txt | 37 + _sources/generated/kor.rst.txt | 87 + _sources/generated/modules.rst.txt | 7 + _sources/guidelines.ipynb.txt | 52 + _sources/index.md.txt | 209 + _sources/nested_objects.ipynb.txt | 354 + _sources/objects.ipynb.txt | 428 + _sources/prompt.ipynb.txt | 285 + _sources/schema_serialization.ipynb.txt | 306 + _sources/tutorial.ipynb.txt | 394 + _sources/type_descriptors.ipynb.txt | 346 + _sources/untyped_objects.ipynb.txt | 198 + _sources/validation.ipynb.txt | 926 ++ _static/basic.css | 906 ++ _static/check-solid.svg | 4 + _static/clipboard.min.js | 7 + _static/copy-button.svg | 5 + _static/copybutton.css | 94 + _static/copybutton.js | 248 + _static/copybutton_funcs.js | 73 + _static/css/custom.css | 13 + _static/doctools.js | 358 + _static/documentation_options.js | 14 + _static/file.png | Bin 0 -> 286 bytes _static/images/logo_binder.svg | 19 + _static/images/logo_colab.png | Bin 0 -> 7601 bytes _static/images/logo_deepnote.svg | 1 + _static/images/logo_jupyterhub.svg | 1 + _static/jquery-3.5.1.js | 10872 ++++++++++++++++ _static/jquery.js | 2 + _static/language_data.js | 297 + _static/locales/ar/LC_MESSAGES/booktheme.po | 81 + _static/locales/bg/LC_MESSAGES/booktheme.po | 81 + _static/locales/bn/LC_MESSAGES/booktheme.po | 66 + _static/locales/ca/LC_MESSAGES/booktheme.po | 69 + _static/locales/cs/LC_MESSAGES/booktheme.po | 81 + _static/locales/da/LC_MESSAGES/booktheme.po | 81 + _static/locales/de/LC_MESSAGES/booktheme.po | 81 + _static/locales/el/LC_MESSAGES/booktheme.po | 81 + _static/locales/eo/LC_MESSAGES/booktheme.po | 81 + _static/locales/es/LC_MESSAGES/booktheme.po | 81 + _static/locales/et/LC_MESSAGES/booktheme.po | 81 + _static/locales/fi/LC_MESSAGES/booktheme.po | 81 + _static/locales/fr/LC_MESSAGES/booktheme.po | 81 + _static/locales/hr/LC_MESSAGES/booktheme.po | 81 + _static/locales/id/LC_MESSAGES/booktheme.po | 81 + _static/locales/it/LC_MESSAGES/booktheme.po | 81 + _static/locales/iw/LC_MESSAGES/booktheme.po | 81 + _static/locales/ja/LC_MESSAGES/booktheme.po | 81 + _static/locales/ko/LC_MESSAGES/booktheme.po | 81 + _static/locales/lt/LC_MESSAGES/booktheme.po | 81 + _static/locales/lv/LC_MESSAGES/booktheme.po | 81 + _static/locales/ml/LC_MESSAGES/booktheme.po | 69 + _static/locales/mr/LC_MESSAGES/booktheme.po | 69 + _static/locales/ms/LC_MESSAGES/booktheme.po | 69 + _static/locales/nl/LC_MESSAGES/booktheme.po | 81 + _static/locales/no/LC_MESSAGES/booktheme.po | 81 + _static/locales/pl/LC_MESSAGES/booktheme.po | 81 + _static/locales/pt/LC_MESSAGES/booktheme.po | 81 + _static/locales/ro/LC_MESSAGES/booktheme.po | 81 + _static/locales/ru/LC_MESSAGES/booktheme.po | 81 + _static/locales/sk/LC_MESSAGES/booktheme.po | 81 + _static/locales/sl/LC_MESSAGES/booktheme.po | 81 + _static/locales/sr/LC_MESSAGES/booktheme.po | 81 + _static/locales/sv/LC_MESSAGES/booktheme.po | 81 + _static/locales/ta/LC_MESSAGES/booktheme.po | 69 + _static/locales/te/LC_MESSAGES/booktheme.po | 69 + _static/locales/tg/LC_MESSAGES/booktheme.po | 81 + _static/locales/th/LC_MESSAGES/booktheme.po | 81 + _static/locales/tl/LC_MESSAGES/booktheme.po | 69 + _static/locales/tr/LC_MESSAGES/booktheme.po | 81 + _static/locales/uk/LC_MESSAGES/booktheme.po | 81 + _static/locales/ur/LC_MESSAGES/booktheme.po | 69 + _static/locales/vi/LC_MESSAGES/booktheme.po | 81 + .../locales/zh_CN/LC_MESSAGES/booktheme.po | 78 + .../locales/zh_TW/LC_MESSAGES/booktheme.po | 81 + _static/minus.png | Bin 0 -> 90 bytes ...69c37c29e427902b24a333a5f9fcb2f0b3ac41.css | 2342 ++++ ...strap.5fd3999ee7762ccc51105388f4a9d115.css | 1 + ...-main.c949a650a448cc0ae9fd3441c0e17fb0.css | 1 + ...ables.06eb56fa6e07937060861dad626602ad.css | 7 + _static/plus.png | Bin 0 -> 90 bytes _static/pygments.css | 84 + _static/sbt-webpack-macros.html | 11 + _static/scripts/pydata-sphinx-theme.js | 32 + _static/scripts/sphinx-book-theme.js | 2 + _static/scripts/sphinx-book-theme.js.map | 1 + _static/searchtools.js | 525 + _static/styles/pydata-sphinx-theme.css | 6 + _static/styles/sphinx-book-theme.css | 8 + _static/styles/theme.css | 134 + _static/underscore-1.13.1.js | 2042 +++ _static/underscore.js | 6 + _static/vendor/fontawesome/5.13.0/LICENSE.txt | 34 + .../vendor/fontawesome/5.13.0/css/all.min.css | 5 + .../5.13.0/webfonts/fa-brands-400.eot | Bin 0 -> 133034 bytes .../5.13.0/webfonts/fa-brands-400.svg | 3570 +++++ .../5.13.0/webfonts/fa-brands-400.ttf | Bin 0 -> 132728 bytes .../5.13.0/webfonts/fa-brands-400.woff | Bin 0 -> 89824 bytes .../5.13.0/webfonts/fa-brands-400.woff2 | Bin 0 -> 76612 bytes .../5.13.0/webfonts/fa-regular-400.eot | Bin 0 -> 34390 bytes .../5.13.0/webfonts/fa-regular-400.svg | 803 ++ .../5.13.0/webfonts/fa-regular-400.ttf | Bin 0 -> 34092 bytes .../5.13.0/webfonts/fa-regular-400.woff | Bin 0 -> 16800 bytes .../5.13.0/webfonts/fa-regular-400.woff2 | Bin 0 -> 13584 bytes .../5.13.0/webfonts/fa-solid-900.eot | Bin 0 -> 202902 bytes .../5.13.0/webfonts/fa-solid-900.svg | 4938 +++++++ .../5.13.0/webfonts/fa-solid-900.ttf | Bin 0 -> 202616 bytes .../5.13.0/webfonts/fa-solid-900.woff | Bin 0 -> 103300 bytes .../5.13.0/webfonts/fa-solid-900.woff2 | Bin 0 -> 79444 bytes _static/webpack-macros.html | 29 + api.html | 557 + apis.html | 1009 ++ document_extraction.html | 1123 ++ generated/kor.documents.html | 469 + generated/kor.encoders.html | 954 ++ generated/kor.extraction.html | 859 ++ generated/kor.html | 2139 +++ generated/modules.html | 401 + genindex.html | 1441 ++ guidelines.html | 427 + index.html | 766 ++ nested_objects.html | 639 + objects.html | 696 + objects.inv | Bin 0 -> 2431 bytes prompt.html | 592 + py-modindex.html | 436 + schema_serialization.html | 593 + search.html | 340 + searchindex.js | 1 + tutorial.html | 659 + type_descriptors.html | 632 + untyped_objects.html | 476 + validation.html | 1016 ++ 182 files changed, 60816 insertions(+) create mode 100644 .buildinfo create mode 100644 .doctrees/api.doctree create mode 100644 .doctrees/apis.doctree create mode 100644 .doctrees/document_extraction.doctree create mode 100644 .doctrees/environment.pickle create mode 100644 .doctrees/generated/kor.doctree create mode 100644 .doctrees/generated/kor.documents.doctree create mode 100644 .doctrees/generated/kor.encoders.doctree create mode 100644 .doctrees/generated/kor.extraction.doctree create mode 100644 .doctrees/generated/modules.doctree create mode 100644 .doctrees/guidelines.doctree create mode 100644 .doctrees/index.doctree create mode 100644 .doctrees/nested_objects.doctree create mode 100644 .doctrees/objects.doctree create mode 100644 .doctrees/prompt.doctree create mode 100644 .doctrees/schema_serialization.doctree create mode 100644 .doctrees/tutorial.doctree create mode 100644 .doctrees/type_descriptors.doctree create mode 100644 .doctrees/untyped_objects.doctree create mode 100644 .doctrees/validation.doctree create mode 100644 .nojekyll create mode 100644 _modules/index.html create mode 100644 _modules/kor/adapters.html create mode 100644 _modules/kor/documents/html.html create mode 100644 _modules/kor/documents/typedefs.html create mode 100644 _modules/kor/encoders/csv_data.html create mode 100644 _modules/kor/encoders/encode.html create mode 100644 _modules/kor/encoders/json_data.html create mode 100644 _modules/kor/encoders/typedefs.html create mode 100644 _modules/kor/encoders/utils.html create mode 100644 _modules/kor/encoders/xml.html create mode 100644 _modules/kor/examples.html create mode 100644 _modules/kor/exceptions.html create mode 100644 _modules/kor/extraction/api.html create mode 100644 _modules/kor/extraction/parser.html create mode 100644 _modules/kor/extraction/typedefs.html create mode 100644 _modules/kor/nodes.html create mode 100644 _modules/kor/prompts.html create mode 100644 _modules/kor/type_descriptors.html create mode 100644 _modules/kor/validators.html create mode 100644 _panels_static/panels-bootstrap.5fd3999ee7762ccc51105388f4a9d115.css create mode 100644 _panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css create mode 100644 _panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css create mode 100644 _sources/api.rst.txt create mode 100644 _sources/apis.ipynb.txt create mode 100644 _sources/document_extraction.ipynb.txt create mode 100644 _sources/generated/kor.documents.rst.txt create mode 100644 _sources/generated/kor.encoders.rst.txt create mode 100644 _sources/generated/kor.extraction.rst.txt create mode 100644 _sources/generated/kor.rst.txt create mode 100644 _sources/generated/modules.rst.txt create mode 100644 _sources/guidelines.ipynb.txt create mode 100644 _sources/index.md.txt create mode 100644 _sources/nested_objects.ipynb.txt create mode 100644 _sources/objects.ipynb.txt create mode 100644 _sources/prompt.ipynb.txt create mode 100644 _sources/schema_serialization.ipynb.txt create mode 100644 _sources/tutorial.ipynb.txt create mode 100644 _sources/type_descriptors.ipynb.txt create mode 100644 _sources/untyped_objects.ipynb.txt create mode 100644 _sources/validation.ipynb.txt create mode 100644 _static/basic.css create mode 100644 _static/check-solid.svg create mode 100644 _static/clipboard.min.js create mode 100644 _static/copy-button.svg create mode 100644 _static/copybutton.css create mode 100644 _static/copybutton.js create mode 100644 _static/copybutton_funcs.js create mode 100644 _static/css/custom.css create mode 100644 _static/doctools.js create mode 100644 _static/documentation_options.js create mode 100644 _static/file.png create mode 100644 _static/images/logo_binder.svg create mode 100644 _static/images/logo_colab.png create mode 100644 _static/images/logo_deepnote.svg create mode 100644 _static/images/logo_jupyterhub.svg create mode 100644 _static/jquery-3.5.1.js create mode 100644 _static/jquery.js create mode 100644 _static/language_data.js create mode 100644 _static/locales/ar/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/bg/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/bn/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ca/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/cs/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/da/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/de/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/el/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/eo/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/es/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/et/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/fi/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/fr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/hr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/id/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/it/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/iw/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ja/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ko/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/lt/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/lv/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ml/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/mr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ms/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/nl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/no/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/pl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/pt/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ro/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ru/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sk/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sv/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ta/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/te/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tg/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/th/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/uk/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ur/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/vi/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/zh_CN/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/zh_TW/LC_MESSAGES/booktheme.po create mode 100644 _static/minus.png create mode 100644 _static/mystnb.4510f1fc1dee50b3e5859aac5469c37c29e427902b24a333a5f9fcb2f0b3ac41.css create mode 100644 _static/panels-bootstrap.5fd3999ee7762ccc51105388f4a9d115.css create mode 100644 _static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css create mode 100644 _static/panels-variables.06eb56fa6e07937060861dad626602ad.css create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/sbt-webpack-macros.html create mode 100644 _static/scripts/pydata-sphinx-theme.js create mode 100644 _static/scripts/sphinx-book-theme.js create mode 100644 _static/scripts/sphinx-book-theme.js.map create mode 100644 _static/searchtools.js create mode 100644 _static/styles/pydata-sphinx-theme.css create mode 100644 _static/styles/sphinx-book-theme.css create mode 100644 _static/styles/theme.css create mode 100644 _static/underscore-1.13.1.js create mode 100644 _static/underscore.js create mode 100644 _static/vendor/fontawesome/5.13.0/LICENSE.txt create mode 100644 _static/vendor/fontawesome/5.13.0/css/all.min.css create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.eot create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.svg create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.ttf create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.woff create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.woff2 create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.eot create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.svg create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.ttf create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.woff create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.woff2 create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.eot create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.svg create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.ttf create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.woff create mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.woff2 create mode 100644 _static/webpack-macros.html create mode 100644 api.html create mode 100644 apis.html create mode 100644 document_extraction.html create mode 100644 generated/kor.documents.html create mode 100644 generated/kor.encoders.html create mode 100644 generated/kor.extraction.html create mode 100644 generated/kor.html create mode 100644 generated/modules.html create mode 100644 genindex.html create mode 100644 guidelines.html create mode 100644 index.html create mode 100644 nested_objects.html create mode 100644 objects.html create mode 100644 objects.inv create mode 100644 prompt.html create mode 100644 py-modindex.html create mode 100644 schema_serialization.html create mode 100644 search.html create mode 100644 searchindex.js create mode 100644 tutorial.html create mode 100644 type_descriptors.html create mode 100644 untyped_objects.html create mode 100644 validation.html diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000..e77a1ce --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: b11215b45f5b2040f6e617d5947c2331 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/api.doctree b/.doctrees/api.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2aaa23d6b83f7a05951585b889121723817e707f GIT binary patch literal 28170 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 F{{```@Lm7_ literal 0 HcmV?d00001 diff --git a/.doctrees/apis.doctree b/.doctrees/apis.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d6b4e6266341af9825257bf975f9a4d315300ff3 GIT binary patch literal 48565 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 literal 0 HcmV?d00001 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..a611274fd5986066e635cab774d1d244b17a6a23 GIT binary patch literal 200897 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 literal 0 HcmV?d00001 diff --git a/.doctrees/generated/kor.doctree b/.doctrees/generated/kor.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5f0e821510a41497e1f63e15f9107e126a548c0e GIT binary patch literal 864041 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 -FE(hc0f^$0u8t;~zZdWF+VI zwT40Ff}FQXzM0SV??OKP!cDKvKdRccXPD=oU_3eneCZd*je>OQ zyaUlAr|wyC<|5$7X-rdo+%G|diu!S{MZO6?j*BGo<9;QKKqo)$pmTW=4qY{F^^}|D z`$@@LGL5pVK#3VlCKwy-AuSS`wTBk(ga?Zntb*w@9c%$2_U%__P_Co zd134+81~LuJ@n29bUJxzR|ltF zu+sq|*9M#Wp^DoOyXjjzZ<>OU!1|Gc=;&?XwJHV-@9mjENYX(ezEJapd39eUCkyS> zeMz-#KY?Rqdw5iO&35;wFJ0fSQxWI~6(=$$;_ip08GOHoX-JgsCm_Z8e!rt3QNEvm zWchySELZ+S+=ACruC}SFGkJw+6bm>Ha{x!zh>$KKXPRw1Oi~;d@jfOuwhQX{oVkd4 zq9*s^sHR=SW1`iN-#wg-`pa2xJ*g|Blv?gyWS}}-V1QP!0dg|n;ksbwk<^eChy*0> zHo7@X**l!OjD%&5G9}+B&dI8=9OTTgu11oRn{_ORv#r@q5>hPVy1vHm6}4~)vYSXM zV)zxST> z8iyW*ttV#podY4P#ySu1obKvon z3T3HJlu}E6hhor|{FamkbN0xP_H)e6Go*hb8oSmEiLTLbB1 z8LtLBc((F2_{3B@dkUy_p$7Br3_QnJ#~+r3xpL_CGa_}n+BBem6;SXi2?g&1`fKOQo|MxmggLZR{9@P#AH_b zABLtGl>QfKNR-kSko-#DA>SV7?~p)E<(f_DJ3tF4eNLO!+o*0#yd0&kg)jLK(&i}r zx4^riNZs$Ghjrra4gH+r0a1YfrCoHX==Wb->;WDb_>bDmfNua@6p?@UEyD z?l6a>+MNNJW@>hSF?6}rtn2{PtcPXMYPJP6+X>ljOk-hcv$N$&GIvPT#lDEMn`eMc zGqK13AeZy4ceb*5y^z>EKK@Or?aVUXUb1)gUD~Vk&X4ZGe5XyB?^hIhEev%+<~`69 z)PS9^59gIWNkgLYN&-@BUg_^?NR%xTkgSFI?3*(Gi9{f`eJi>t^LuQ->=kix#hr7b zvo#b)U*75I-y~MVFl@zL&#dHjq58dxIHF-0SjpBIl#0Z-7&`S5b&$t0-}obNo##B!u} z=JaSe^4J(7A6S6Ycyi042~1uCQeDt5PBsC2~hvskO++ua)DGY(sJAOSY0yVNL)f1y8o$fcW$CPFqCd$Yn`MIdq~ls^+=j zSQF=+b^=K5Rqw(l=2f$&fLAThEwU_m26%Ij;e;)o*>~0s#roA8K-jAu?X6cW!FTeh zPo}1uV3O@o!%Lo0FxEa7D2__+*m$Evlr4t6iIh)zbL%atZF>gUH*=oxor=E9p7CEn z(+r;Rr)fx(XDlGadd6R)AyJ;OfK<>kzMn+EREU{8f})=BeQdxoc*dL?wt6+Om+5-p z8Nb`pzvpx28S8nKybHON_KdR!BzwP^@(WE&W|ZxJiermBKjh_1k364comFwb@6lMM z{GJhj~7&%#7fahy;qXNoRU#e zjA*B1t7_ZREhs6%n3A?PVQm89&sGD?y)-9~4=2lZDmuK*2jvnpp(!{Yu`a=DXh@Vx zARu{D2KzbW+e7?j5@>FF@4ZPTdrR6SZAZ;iQx^c1@-W62*#3n3P z8ije7;TgcR_!cp+{_s0u6PD}%^ty+UMifhL!uor_gRAzh;1g5r>?xqyT~m#K%;5%> z%I&}ME>OU*4Oc-rLv3IfuATlph21|Y?ATKZyFr9dw08QS>&vi`7o~x~ZG=lHlO(ET zSX%-ZlE!_Glr`Dz#bsaxJIM+D2P@q%2=xVd24-~$gj*f|j9xREnTrg61%qeq7LL}r zzi}Emfd{2?5vHkHTtRj8(k~RG_6xh8;}F8Y(i#t_?Z=Bv`H?o?erZ{Qx6IlLit)mK z$-HTsp*CLzst;9vVciBR7ZiQ~&Znj{nTy>pq;#?6L%nh*u?zfap_v@o0Xyo(MIUx{ zDq~}pr+{!c<^pTg$n4FFDBGo##Y;TR;}%vvo}@Ur6Z#GnR_=$Ulq)agR0PP!u+Qz4 z%|$#SVH!bDV`U%a^55kc%0KNvTThcft#3Y;;}pBT`2rde<+2G#u`b&%4T(}80+PkY z?CFH7Nd!#0+1+%)!dF`N7qCmg*@en|$v7Jn2-j@3qL zt?51N1GvUzVtP-qa2|vugV2iKMU4W%@1l<90;Ud_ld`0jAsEl0Gq!|hFUm4*GPn}H z6PpZH;-h;<_44y4T9qB*hU%TQR<)#LM-&_r_W-EXf($K`%1^c-Y}h0rP>^{JTQE#z zCGhV#9}TADJ(ia$D$HW#A%6LHF!e&N2ADlK`Fx46WFeJ-Im#Oe3(N*)CUf#?XUL;7 zCvB&pEi2?z%m_0>=H%rHQu`%6%A5$EPrJE_xm-$QARzx#6Njymyj$VtTOpuVNi=QA zyRaL!deIxp-9C~Mx4;sr#xG^luLXQ_*>vVYaI^kd=tG)yPCwJ0*9nexH0#eyoAo+7 z-4kuJzb-(@`Dz>OgAAi>c5IvEd$A90lIQZT9E1B$4iI~;WHY$mgTC?@+#f@`><0HM z(25&e94c;bC5?tT?ftxDa)E{|&wqR`sj+=vvi&KCP#OUEL0=zpZMmS(@BE zTApatMoN4Xl}(NQUMYs;_XxKy`JDhS#mgRfpGBP^RvLWCYgjKV!}ZZnp1!er7}vd; z!{xED`cAl+DB5;ftLe`(lhu@}8VbO5EU~0evYxWUsqKEIg%87XR@n~^BF2?N@OLFP z%%1f9B^OzVxGgiZJvm&pZC}${TN&mGvtiZ>{OnB)S=c?=zZg=K_^c}FU#x(pU^?t{ z@fvBw_g>>@=QC+YRB}x~icPLPpN2#w*El3t8sNONB?f;qm%qYshfFev#d0k!$#U!i zhfX(64uW_2Ogys|?BdvbQ%g7nPoNMpgL8;rtk)5#Ml7Ps4j|O?FxXh4rWet70v=*F zI6m>+;P{kUre<2N=rZ-{3SK*sQ;(Bd!7aVYpcK&Bshxqo-W?r1M*!s-S^QnYutB1(+nE-<1{2n;|fTzG<}JN zL}^?O2{f+er!6P=K`yPUg(SHH`*5`Gjqt9h){U7OQpfh-%z#%=nMQq`U|MdCDmws; z>S12AMtv0U;2QPU_{20Sdm=TewvFy0B?d#{x+59A0){H4w;PHLvEgk=e^l80x5AD+ zrLbf9rlR`(RJr0Aq4F)CeMM)VU3Ts0`7Y$ibkB~C*Xy++D%UUU8GPui_6*MAX&p&Rob7g@*i9k(~Uv2{QZ;8pjO5^A?x>$)!`sfpm9t*=e;od`;+f#etj>e%wd@GhS% zXA4{`f(k4XDCHpS_)MrFX2bUr+|6ynWd~p(Jxq(X;qL`JxD9_FJ~124o_b>?Pv*Pa zvf9XqY?$0WXYJ+9Vj%;mec7*LALaf$nX?w3*|zcXVvzGhL4T*(_HM;S(w4T2Y8PF6 z(Z%m6gfrX1Z$r}zw(!R^B+3>FNM2jWXtoFN5fYNA(lVJs2C0B1=Tt=NS1n4(w~!!5 zzkU+l71giw9jc8)=e&Vyk{d!$!hyagTQms*Km=mXfZ@~nJ^F?d4A zC{SP(>k{U`dS|PYQ$ZBWj7OGu=|t6b203kS?4Kp}R0I>Z!nb34>NLK|*@!x`GfzNS zq)Qdwe5NT@jpyIu+99yn2JLaR%slHhc{~FvD!;vOD^`nm~q-}lgG?VF1Nh5Tk6sP8{;eZg;kG>5cd1Ut;d}7`QdkT0T0^K6@ z08RxH%U!XI{>SlA{)hDP0wG?z+(Yj}!tUgIr0NUsG``6g@I0WmlpkS~H4Ax(Z!q<1&`T(zAseiiT_G`7ia5%IJKp(0gl*BP*huTFY`y4i1oj*J7o;Tbuj zLET<}7PTo&Ce4I}@N%X{7UJljg%H!i*r5)}FS%zn)0i5?lzsRS3}#XLumTw-?w#hs z!R*6Ng@AXm4@VibWB9KB5>(7fRgUTOnVOl&=_pry$*IxeCGEsdm}E2LPZEtOK|l_R zWim-C*aO-e!g2ixr0K zDTQHI3Jjbu(x`yjFsx1q40G{7n^v1Bjn_w~#wsPlVnG0XjPd7CpuH0|>pBDND~lVh zAj}R1>xv)3vQ41zKy##8885G9wBl6&&7qBKXYgQ&-*eaCKZ!q@L%4-;w6eW9bk4*G zd=3{{JHZy9G z(!>uq4AIMa*sxjN2KRU41>W!@{=bO`{5>^-h^q^R6gG+=EodY4MrDXgTT}cybaA6T zKG~8t;mE#O0>czKS4GPP!q3QG&>*=6CSBNG(sc|Ps%`IuT$e{UJRs20?+^a2lsR*= zUZarrr448|OB0^F8oObR3s#1Z>SuZ-u6*tWkKY!ksiEYO8{P6uVX7(=;S%c}768_?W(?9bJ3Bx1avj zX7}ABYGyE=$@NczrE*fl(d)0VF|`Ad2qCcjDU%EtG>EznZ)W}5Lj9~bTkaF_d7`P5 zarL*&^+!prlk`2z5w=sKVIlt`4T%zR0V!6<7rdP^isaUM0m%~bC1}cneiY-cU*bD7 zv_Oyb`Ghn#caa6r}#gCb<5&|Em#aZRKARo~1=6@?V(h}3&~fSyYZ5J~-W z7`vQBgz!wch=xSX6aguArfjAmQRYBEvStd4w47mbBM4%?L^ZbuWt=1+_pFJ+BwYo&7G{}xZX&zl`O|~vxhu$93rgV$tr?eT~dKqr^wPb(-)|Y*srkH-FRaQ z(w#KLRQ0aEViZTu?oZQ@sM#$b#m?@p(U7RwEg)I5ds*kP5QE@d!<;XhJ8P8plUSOf zLm9r*0x)WG%oQl8Ij8G=zR?ZuZ2eb~8gdy@K=Ly086oj^nE87Wd@M6l3%+6S-Q;R` zad+R_NRN)1Gn}io_9TsU#!0r6MlE8J-EL$a+HiVPxFe}^oU3R^cS1Lz8i^TcT0=vM zplQV{olR-a#;lwqi~nIO-wSAXr$T2IW$lBTQNk-znX;P6>@5~%kAuvqop138 zLfGcLpCpB}c>QFuo3^iG$cx2cp(i+`t}}lMC3PxA;oH@z1~4OCX{B% zA^Q7~(4JzVzldtW`+iNWHhk|JgJaT@?SbXh>ZY{|gI4iWUDC(U9_rzt2ak zlAv$flM}K41~|5QKJM#K#EN^J)ed|C7UwR zbOjA5f~IWArtLJm9LXk5us!PLl!{0;U0R#)?M9Qy>&Wf{vU0B z`FfgrRC?)JXqq9tbTbW!@|OjqST%eb4T+LK0mWclJAES_c89)9QbVeE0m;j}!7P)<@oc|Kq7=*El;4yMrEYRRZ1#Rmk{ZE% zTLF@0FXIIL9gSMV1dTO&bKXh$N#w$JMw$+$Aw|%X&Fn3u;pH%UoM3y@%^Be}dmTS# zhm*ZKbgje5$42k3_V3M#Yj4}W=aDQlNvE`JN*TnVl2Zws2{^kuwMPpUdH$4 z4K+In^X1gT&=Wee=F=?V0_9a(GOCyqtXI>|eMtWKmpy_h8A8g<9Ez`)2h1I_5Vt#I- zItVN|5sFqUlDq%;`NV12y@Ip8s|GNY2dXuyaL7vPsNzyO00OYLcXWty+hFHB#+M=`&PrM?+9% zZnQoE0TFEADb=_8aY0E2LiM5Yi`T=sCMa}YZk1Z)t18V>d7{M6M3wk(vbWu4qabzml{FeaTZfyi^<$Oo*MFGvG=tv ztU*PZsa9!wZKATWH8p{Q)2dcV7hZS~oXmoUtEb?&S8F$p82;I)G$-p5%?cd!-wk?j zv@|tY8m&yi6SQ1dpMXDF<=PmqdupUwDmPgpF;ep0dN`Z~C&t(>e737Wd9t9Rhw|%u zD8H61hU01>ZNYK>BTCol(QDe$s60{c$j zP+qeH*FB6(HCy#@sH}jKpt7shY_X{{QCT?E#HZRs6>2ZE$`d2_1BC%NE=UZc#<(T!BgFj~?EsIhwL5}-%-pZVzCmv?mM z+M}CKKi}OxW!==+SfzDwy*AN0TaCGM&6BH8;SemVWb3{k@^X!8#4}xl_%A9_p1LnWGH+YGb#w19sH? z**@%&yb;inVeT(AR{_gcxzlgDJqJ%Vk4`7Y0K)!INTZVqg&qZAiU@@c@s0L0s{t%y zA_R|q1;#{tNLWntn2=U)Ol00ZSxaA2qvl=1Zb}^z{ViTgwMVc>jemamobStEMg1j zr4D+w#>sYJ)ZFUc)!)VBrm6q57?Q~7(*c&R>K`VY?777i&Fe{1y7)^@HDQ8sm zF-b;o0B82F_C9-+HX9c?dVwNV4|Y;VN_o;DFbYWvKjCv0 zRE?R#Z|`rg9yNf6+qYrsU_qhV@z*Xf`fboxo|*OmXxAM^vz7f0%$)^VQfZqu{^b$y za2ghRXUQUC+|~;oTH)Xc=T#;^QMVv|C~adtX=xIjQjrZy$8pNR$k9^Kll%kX(wBTy zpyaQzWvV|x&&>K;Oz9YG%j@l*#iOom6*bs_v7pDrGIlGnU>J**)K%klpu8Pz52 z#*F!_1~MIrwO9nrB6oh*^UIKfB8cYF!n}b0 zgMtGNs5gi)l13?Te}UMFIY9W zl$9~u0KyHW1y@|Pv)tIxR8{!aPV7!y1^~@u7D(p|_qBjYkHdMZrUP@|K1a?4+I{<5 z)wcb_4vX!>o$mT@u}tPpuw8m;S?A6~Gs|7+=loWIG9v{mr5D2r{Po-9NgWE&hAIoASI(ou0`Rq){l~7XFEiz3sL| z2#alTOtPdyBizDoaoMsWoqe@J0!<{O-P%bwYsCuo8hmejv{`%{$zpOZ;ZkS{l5R=G zT&^4?Jo%>$^CTK3wLM$Fw9hVui&U+pAyKnSK#HAR8)-3l zZOi>*;kyCzrrr$3A_K1?qj3Wp4W}4Xc+2}8BsJuwYXQkjm#aj8=LFb?Nl39moZ7rv zH172Bi#vFrRQEPg+01MEGD$@QzdFisA|hO`DEB(TJto4H4urWH-&C0UahQr-3v+*l z0xrT_KF3*f_$i$35n=8TXYuv8z6vW-_FeG(t$Lw3{tYokQB$?~x(x9DHISEqe-uv>e?cA?-RI9MxHQ z_`DJAX_+Hh4lf+gUNh4Htwg9(JUdEFLcv8hINB&`?`w}y8~3;ncCk51(#f-5D&c3U z@Mw@9Vr8>RZF1>TZQD=iFxc_yU>2?lcieK=ySX%Rs$x;*IQ2wmnjua-n}$Sr(gISf zCw&PGiSnccBr76G=l%09O^lMLnF^Wmu~Y6z8pQ&h_Et8o8Ddb*G}}a&q&P9?5bNJg z!xW4`ZzS1D#-Oj}*jOVjgHEyELjGwhroW_NQZcB285@JXkA_6e904hI=6sxnM9mx@ zAG61xUnLPRg^HRVy^2A<1lYMw6d8kZrevHM9Y1F=sJ3m%N@Q9OV$fgrW-z)HgZ_$* zMsy51>%EjCLB>=9Qfv%*00}8ph*L_wXbkG*S2zYemZTzrUmfLG#-LtN?sW{hth4(Y z2thTvsSxx~5Xr8Epl8DX$PkoIaTd)zL(EEWy&i^3?&Rq`krdJA#16e2m-z5t40q=3 z=ri!EGI7ZzIQ)Id#iSINvMdA7!x2Be6Y?U_*wvX%GZ}bF${_GmD$N$6&VlC+0Lj-< ztN6qMPxcfFJUP17;Y;^)15hSWlzYY14)Rn(fnxY7xhaL=H3~!al){i5Nm;^$Eayqb zyW7rg^v*|UqP97Q&Oi!e@3EzFpn9Kt(LP|4wL5->4$ZtCSZzj;(T8Skbs9QuG35~< z%nXNSZc>oi+j@~Ru=zgC&!cqpw9JPT1-@94J}slEPd}DrR%!`4|K*4Gtd!W^is4Z1fr& z^L$Lje?G=u;$>E;-jK&$z&5Sk>P@NdE=xvhU7+ z5L)qbFen`S91KA=N~}2jGBY}i2`G*Y-2OBeC2A)I$T4S@Wd55B>@6B|S6;8x~2IZu41K`~2k8h#PQ z{?6x+PJ+Jj48U4wXAFRF5c3RyB9h{{?KnFgH#_=b4AT!`1|ff}qc6+lt{gZ<4~G@E zm*EgSU&n%^zj;z#Eoo(Fp)7T>8ONqCxsn_r5B@XcB{2=-<f*dEKzXs}C%vFoWORN8?H z!mE|BNw$3!N>Y?|$n#0C%K)zVooc{0y!eM2mM1@=S{f2A4b`mDknF$~yt;&Uv@Z3I zR=LF1qhNKG6;#366R{TAytr*;szBNyFah_b0 zmnT@0!Qe^WQ(C9VBSXQ(Roh9|$Fm0gHqr_NjiXRjeI1E7oXfhZ_hFHNMW^-CQ*CNh z%hVp=jcn1>K8cmw0*6{vOnl1bGmpV5z*m?0%VNWD|5<~jGm+uL&DxIP<|HWJ)g|>+ zssF6A2$LhV^5t!(p_dQNS+g~Mb7DbpDg5JMWke-Oq)$yf1{U#g<{X)${ z=1F{7A?%NFshCm|o7{!nu#~-dA$OZv*|itUs4ue~Px}r@6S=@~H#E(#2K*omiCW1L zkYZP|9;P8tc^d)AS`kbyu%et;A*D#bc0Qi=M-nyD)3E}$?jBD=*WNsy_Br@lxs!d# z@7TCH^PXDLVN|$%qSi3FR%1C%XJlh11`z!A7%H)7esfkIZ zG3dBN(}C?v0WB)FkX#g-_q?3x^}@;F0lODiEzvlpGFNW^At;u)N>FV1xwH$Ab$r9# zOq&uGBD`75YHyazH~_b56BO;kVsDsnVxfR^t5{7w3pJ zToEnv$VaTC`6i@^2lAJR#*}oT{t(CFBsZXwyI3cobrRxOTpd92rJPB8VoN#fDYa0- zd_;+E3X(aS4HRWs6HrtcXIp=DT*|plVfZqIA$v+;*p;Q6lX2!<%Ie>pouMY$@}T$a z_T}ti%u*8VFduF+w77FCFyGAXMEkjSI1OzpK>E1|GlQS|W(BET?Nt<$9!(a)bajd6 zlZp<%`}WSn)`6;`Et)! z0bwIukGe@L_h@udM)MYERLp3~zF1IIZCSN(U znbdnskWm__Wg%KxvQ|TT#`~3MgsPz(fuD3~72+`HE6?~J3+=iy{!}%z1CUbgIR5|a zeF>OdMU^lK*#jg52ul-q2}pO6PKThPL^={eK$b)X!e$#gFWoQccj@ley!VVN^hITu^ZtH(YQ>(NSg)QB)k<#%ZOkoZ4!_a$Loj+0OG0an)6g(d;fFD&pM{pWoid!!Zj@zLR3Sy` zpk-S9EM{*Ej^$0U_sdw2OtHruJ)LMjCD_$h>FSuzFNuJ3`&HBBs2aGWCEZVVIf<%$ zQ0hI;A!sinwU0hUI+kSq3W=I&FD>`5y-8+t8_gs$I*)21>x#a}=3-HEgv!fP&Bwo!sWA(jxw5eN{{=$a&cNBo0Qd3aoj3xGrGe3x!knn`swn4d4qZz8e4Wdd23zz^nk~f1i&OaW}q4G^Si(9NHrPD|rE(sNrOf z+w@ZYGXW&e|8Byk6XwAGv8P0Kl{qaEUC96DE|wR2$kUER(_%96uwxatH)a^_pm6UY zceUx`o1q0bzbDp_&C4MOrMY7h>768eGFer&-;PAvPL2cGnY%)@?aYqybbj)}ecPk^ zKXD>jQ?V|y12_RqGdO_Hry)@epnw$W0KSrjL^*&0lH~x>$BOwExaoFkB4Anaw~#2C zvp^=tkVb*pjh^DIyphR1gOkV^Yfm;NSurPZl=W}NJq358f0kr1xf}gc92-k3M>DcCHHRhl#%fl zrYjjn24_mfk&*g2tI^T(Vss@+Eg3!)J`t_AGr|bojh-Tn9zZWKNBK`gJATMjCY-?-066CMS$aHEa_pSC6 z|C4AO7|coh-C2aJn4Ec}vb}61- zP&hSwLBWLP4`nB(ZBfC-CoPg4a`8dL=YoTnsY%|jQsg{u``j}z4D6Rm@tO1f2~z9n z(DkFLZEJrD!H!)2rp`k9w&GCc2=yD#G%@@8PZjaY7KlD)0FLolf?T5DOtWVPb2f@apI_m6V;%2TF#23cvXzWJAIGT8 zaUS=RXqZ&=DPV?1pPOk&)W{K#LPyTUG$d-|xcHbo`mB%$m`X)C?wyK0%Ya>`k-?dg zab%=^&Z18}wMF-$z3V{q`HId6qg~PGKQU zI{D>~K0iZJ5x}ohJ(kg@Qs~9QR@2 z+@uAcp2N8>-{g zX0<$8eRgHA2`ldAz3^CY2Mh509`lkb>V=ivlU?uoh+boHu-;J9s&yg`CNW8ifd7eT z-4kP%y1MF;aVSw3aIyt$ie4V?g(A`VcD4yV;A^(+qi3Y8TUXYBiuubQ=+nv8sJ8n{ zaC)nH7a=FPU55Nd88((uI75-<3VP|3f@VwfRP2WNUDk&7bK0ahj4*qV?uo0Y`+!!0$#-56iTJr28WoG5J-3#!?ZCuEH{!d6h-6W#en(1ZeKmNrD7I#nL&hR;@RpF;jD80i{0h=({My}+dPPzk+I9x}%5LeI!z`J#0M z`YTsMI6PcNIm#|&R>b|Q7GV|H-xci^QjmMD?Rq5BW*~}-pvACi!LU3tcfIy4t)-k> zPhkPOCS|I11pi@;O++jl*NC*vp~G?Ab>GC^^~1Fx2xjqA$J(wqWYkR{=r+aW3*jcX z>UgE3x-d@DERPSDChE1Tt8fy`&dKU%a}A^*)Q1gre&kSXY^*lE296{w4V4>kSFUtd z+TXF3?Tfi=U#KMIiVfqkg&hO!<)fi1xpm~8*6IuQ4wuK9)uBtJs>ja2*9?agPfVVD ziN;UbX>ti1(4g=2Ha z%Hw<2mv+`_qbo%OYn>%{iatw_b(`fNL6NCbdcYC{x5Shn_;i&!VhwG}K%TCGFf*L4 z@-_vjbw!&7vP>D&Cky$WL<-b&O>QJqfcWu3?rQyIy9kR(pWft zv9bC_3RcwNDK4z+GLQa3dM?!5S|nd(^+*mG(cH>LEHs)+9$D{f?mR+rhYTTp1WhyK zcYa4hqVhWeQfSOM``w^G-tA!I@Dz|NjpfaGN0k)FvS#?$pA^iZBAqB}2ig1^x! zz{QiKaq`rk4%kXk6~I$F1_&6-b_0`dv2?(H@u6?otp$4ecG;y___H)f{14j_jnd>E z1=+r`i4q1t3*jaBQX|kbp{)KIwP(|iC`%+Dg<7JQ(vYa^mw;qhqFLx0F&?@TBm8%p zt*;|dFd0hOo5a}QpmGj`e`fNEc}?j8&ZwTLpR)=Z=Mb zJ=L0BhhS-VD*6_T9CyYeh+I9U1nd6$fQsn(-j^$}@#W`P#)MkcVQ3*s7WB z{IdUaD7Q7t=71_dpglFR)f#cXfOgrBRr&_B;^&v4fcg1leyY)Cid$?t8cs0PLg`YW z4r(Lr#XsOZATOTy`X)5t+Gyk%PP_y%1m%)+1u&aa8D$v+p?v090%0F36B*4%;9b#N z{KxAun&J~!cQzbj{4e#?ZeA=gbj^zy` z+A?iMJ1?ji#{8hD5o4 z0+QwaWiPazAQ3Rlnl%;0&PqxIn+wDsL0MBSAWlw3EX152H3fA=qfBo0TpJ+hRKG3~ zrzEX+^l#E^E?VkQ7M+GnV`IQtwA>?z-anSda*cQbc4TR5HbW-n%)G8MLYL(t9Ap8p z|1%Rya7FiRBspXlEFd{k3(iWLkCL!V-N`gwBIDdkqCPeL= z!+E}nzGKGlUJ_m?_YwoxfY)wQ=pRTAlC*^IE_BE~Ruoct*d^}na)weJ%c!@GrE*A~ z-F+IxM6P`W_;z`7?JU6MC#f#JU8mc5K*@4?CkoFI(iM-)()VP_iW*&9)w2mRcdRTC zlO=F*D^_LUZLJfceun2kRc%Ii12r8+#{rU%{5%%_$&~z@u0#~$+0g<$;Mt#(Jd0+| zPVh0BYrJbMxUgI=!x^S<->pnQnXeQ(Sf*}W7G6Yi01hy)4;w8LiG%Yo7j>k8fQZ($ zY>#9TU9*OZvkcep4wqDVtS4G!v~A5&KR~$8|F980I}^eyIl^Z`BPcwB1VZV->t1bK zU(R@dznc00-z{RAXP~N(Nd5#2iTB{Q9Xy@h6+M+k82f{^@Gg zYr2Zey{H2BOOGr4P=6~j8Dr`(#?a^r<)~q!aOLP{d1avyP*K@vVu@e532)%?JQTxF ztzNG*CTiouXcBC5AQik|FN*9|!Hz%|UXX=pupk86d6?8_<_cXv=4R3bQWK;91^WUB zNQ)zvFz8023R{|XC2OlP8jGIOH#WZq$l*2Ex8W13!Ddg18f>=8vMfG($d`&@W{X@H!p%k0>(a*-N z=tQNdSkOhlboZZaVyH^M>)jvKaS&mZPIn=lD z%uT`7Cy$GX$y#D*9cEOYSUuatCMRPjTp#9&&tl=~DKRiHZHRsk;otqN!#{ zVt2*66iA~#yE=kzK{sm`#PgQ&1eQGvz_uP$+W^b9Mx}%I3vamvv{!wxatf8Hk#!Q0 zwQ=K#dgDfUCm>QDYG&EHF;6y%4Xj8=TCy;B(yYfC+T)3wG!Z7Hkg-W~mx9!KX4@xC zLm9;UsrO5mr6|HYnXl~m>Lm(G_pC|nkkAxHFUD??wIgMWU{x7UClr+hJ@yeAPvSs1 zG^V4Lnu`&Te8;-#u}{uO4Z&|F`A1eXycU|mTxTco{FTe^q9IYGD*{qzHvGdhBq|#& zAX%j=>+(v%nHqMk-G7n9*qSBhvkFYye>N4R)w+bQ-Q#p=R=WrnN1luEIruptYX2hH z10*?QW>`RSvTl}Rb@5RWRBp}%FGsYOaWme_9RN8k#H>3tMkvP36~-bq2`wU_<>uWX z_Vi6wS+$paCy)f?);q_69qUL)p{z@+k#n2`N-EiS^0QvcWt8@-MMXlEj1v$ex}3kY3PcNPeYzRbfb>O7|ujQeLI=Skw2A z&~hu@{0$3H>Rp9e)8$1W*{e1IVVK>(6pRe(MPd1k%$2ttOULJIf1xu#whGHnb`_QfQf|hz$q{n0&F?f^ zOA-^pwou!8Jq?Mnt(1UVvFlAFsN522SM2H(kw55v7fDTsh@6^jl(yN9{)b6;q1;P2 z4F)`_lrE1|@O$51CTR)bUFgj8y`qrPCmK;o=bSt`S4wxdYoWnYLZ?wntPhr9dd#~% z7_p_MA445R^e14mSR(9r_MELY4T(Hh>f+-Q1)nOqJ`WE(tFs~^*s3f`c&>($GuWJr zhpAPYs!}g!Yc+DC1$TlE))mdee~gL-zds_D$)<;kvjtkf#m<-OEz80KS*~{sHd-du zE2g1&@4;`MxF&T)s~JY5#>sL$y(8JD zZ7bJ%R*W$;x}scf02_rX#~IGij%9kd0tL&Y@C5!n{8^c(j1M-MDSk*R;Wk*M2~R$mF-R~R=3YKTW_ z!>+SaUkl{$y1m!o6RX=}Pl?Jnw(g&$ZckRk0D7t{$)-z`75eM;-l?#=MPbLD64;q_ zdm2bj^gO8NW2dUFQF_}*p6BX0c9lHI70*Z|PI6ts&Y=*~C_h_A4j9)@Y6wIh21-GR zKZySX&yjeB>-$v;c82SDx$8)7X&uH97H7C}BBokP_*;H}t9WUbDryv38&j$VczgHJ zt+MaelWh94qf7G+t5G3xW3fCL;$!~WU69RT#K zoSw6BOYgT0XK-;7FS+gSIYmeVV|D@n=09I!L|>zef8g<+Kb98>&T%Q ztJvG+kN!9KTZ(&h?FA}F!yqh`X{ zfTB(hA8oYv(r6z=oQyfi@vt*n{`#_)(2%Iw838FYMSLR-iAoU*NEZLtf+#Z3D&mG= z%7>6+z4V2@Q$TS^=q`*8Y)1pkrDa-34%s z+D7y0ssDkW;+8Q)x}iKj{NHR(BsM$(cy3P*{Ze;l^vCS%3L4U_E<5`MJYuyg%BV*t z(~tsaS~b&{@@95-OQP`69)}xfSf@fq*15{9!y1zl6SaDCurXGyH?NwkH7kv&>oHBY z624W$7P2}^^kLD`Yj&BO)I*~$qlu$z=f%)8vFPld8Y?s;%E$;vp$gxiAyLX9AX!Ex z&!N#TB2ma~X3`IhChW}fn7m@6KS02tY=09;Ga0xDwujo8_t20iJCjkBK0-qZP$kRG z%x2-OG&SNc+uGbiL(E}qILU>q%^5l#SCO?5f%DK?{o;tZUAAeS>{RkYzpz>IAk7j= zg?|7|GuWudXh@We5|Ba%%U@_nlwt`;mW^7cm>((@ArWV}!#vqrY$ja%0m_pIwQ7k% zJiI{{PZm~CshS7Ez#RnWC4}v-6*-ZlhOBoGketkO7Lc7n!phA#xwj_0fUJFNJDVgW zH`^Q$<~9;iDATS12a`ph&2oKrr8(6~i!do)-Kk>!im?%rf)HMX+LNnkNR&Mxm6@6L zm>GB>2`f}C2{Ry-nS-1j8}J&Eln?MS(_sZyEpGTucDW`xG8joI1L!#o*j5O_{AqCK6#iKLD@l3GRgO7ID z)udtNh(tNDw!}@_?OX#&{haL*ajwbbE%aSt-9p6{+w}!hTQHNWuOPy--o56j0I2);6qLrw|&}dcZM1ZCa$|M?ylk{E(NFV>H(#j|swMU0#5&`5JZ>2~_A_ zJTy`nD{qB@h2YbJ-WgLbYvHN2$~ZkJ1fYGW(EG4&zH)UO-8!c8?~fs6XUnqPV|54g z70>IN+HNS3wL*3`w99_h&|9DtKWhk8hMzT*Mmy@RID)8Mr6`cyM!`~52&m3@=FnH+ zJ8|aF+whT}IiyedJp4>~?=>cr;3UV1NnHc({!tmQ=zi?6EBdzRSQa$e@-(F(uxjTZ zGpNd2o^woj2yal5rzl}ngFZEho#lqF`uJC|LL&(tEXTRU3yl;ER%t;Twp2DS>bbhw zsKO2M>)GAe+-PhRCm3DIe;Ux^a~l-utXg&D9*EO*;ScQNW9KLtpYha{ah22@Nk1R* z@=v7=tlH#%NmZZ^mHWMF+jdskg(I8W!Z4BBvr0YIX6#w?VPzTTiaywH;4`SdZB8Hd zAwHVjgN}6Z7D3ZQ3eUf$w48=S z3_ngoqKu)7k8IyKQG14>wwd}h5&=`GD3g}RK!)X!O5 ztUZ@#0WyspFKC^fU|Al&6s*r|Y5b`z(nw4&7Q_N3@ple!m?|Rej@UBn2e*E_h(c%QcJ(g%91xq7vAs zD;z>q=I!`J=}NQ~ph8Tx2LB1(QiPG>ZxAnj!SO25I6l5ifnr!I_NGaSpcAG3_P|L$ zQ~oRf$@ivh#wWHnjXfoHf3b*5qKn1wdBZ+)t3;^>oe>uKm7C3ab?0QW0$Vf=mv8&5 zs#0sahK>N!w`(kB%4qck(Uf^%uT`olvMbg*C21CKJ&P1G9dA8DwQW5uZ|It&huJ>s zU|qHpjHL7g*UDa{P;+fsAU&orXbM9sbe8=`8WJ_j3P?`h*0Ioj0}06-TGVu!FyN^R z?J4spr@|htCNk1+i|s60X`)di2*s@%N0-36oc6Mn92~-WwpBfu4Zcjs!fk_(-v>i- zIr#H%8-~dW!{o^hz~njDfDMJoo3G4?Ye()!0S|8VK88=s>aiz})e{ybuf-6v$_PIS;F?(3>;YjYtJr^!g#x7=l6 zp)toJii*tE@JG-zgEjme4T-Xb0+Q1j`YJVM-xcblWHN~wTmgqx&|}NUpCdV%B!!%@ zD9$Y|WzFd7fvVv($l4Wft8?TtmUUxs&iBiUH!Bg5FXg&-`3{fh9_bH}i<1BhWA34 zw}HfX40{Pau^5&;btZ;AvO4UEURf%e1)X?ILGB#gT-8M^VkJ*M7$^0Xj#4Alw)NCP zQ7Y1%j8B=Dnl1nKJcUu_h;tt_%@A?Ef`&v{eF4eoH92B{n@LEyjegM>fKw4{wY088 z&q0D>R;vQ<@>(sW_|jgrK^d8)+ATPr+fvC6z*0Gg4z^TZ0z9~-`Z7K-OU0f#W2uhD z-Qylxb+F2`;YS6m)qG~HcqcJ?mAWncVIh}1nY9O1+qBc)ctP64-u1(^Avj73Z-a)T z++y@6trqv&vYD+vD5Nr*t=~e^3}$QYM@iRn%)gwqyx$RcrkcHC`Y`C<- zM882X#SGW?;ay(CWsCu7x>8Q;3)4wvydDrbmD_m94#0Rh2oE-1XMq}s1yX$C3#9ne z8RNAIj@GM;4i44Epdh$1Jh-b`8HICU-OHq`1ezNnS1Yf1YpwR!1a~i}GSp#s$51H5 zjN=hb`ec=n=U01SVvrn|w97Z3+O{q# z6z;j>yK3rYR69N3FNdltIx<__acG*s;$BBXqAad}J?jS+s<{AezeH{BVNk(ptIf9a}laO*VtY}c;)G&XN z@L`gQ5PpRw34cRF%4-D?xglGBkxb&gN6U^fD4hyPZcvqKbH5V=iHmoZDk)M2l{F0iszY7cax%$W@@sLbr00F}p%x8M_t9ods7b`%&F zDXv{E1C#Mx)!m-3k=?{##ccSoKU!QtM~l31T9A0C17IvRJjlddDxUpPDF>^<{S>Kl zbR>AUYMX!8ql2X6#CN!ibOtunkX2`ax#3fGcwO$d6tbDay{|#j4B_4nX-L!rB_L%A z_kKx&%kAH_CEOGA*iM8$+?##3JqgZ%UVkkV;# zx~hmoE?3nhHZAk$Lm-si{baq2&S_~^tm)QePCkmaCy909qPlcs=NF2 zkK47gx{1Fn1XkOrR$ICQ=kFh5YGXUD2bqLQ$HBB?w%hR1SZB7SHcbbpfpk?71Lmq8 zm%>Q}tCjYpgD$PnKBx9BX0wZX!YAg`vL~NY z%Q0?)Q%kOe#GP9HaZaaJHqPSI$~JDN*7z0dqHt=(OQkVvTK|lYYM#~MPpYF=U&bDjzT-Ld;3jjn!&w&n1)16Y64Ow_x3j=IMdQ(+A+`;_g2so z>fX-#xIJ;(Mw4{VD9*W7GnSH|a&xWlYDPwmts=?D%`wMn#*;}%xfxb;HN(j-|7yks zBo!h23UzItK|{)G1?DRYs68NN(nm;mx#eTPD-ftTrQ{FPo16_#wTlC?wmt zG1(jo3H7uYeFH6aV!pe46`W*pZMU(3ynB5~NxP>!K3;1wKfRw_+E<7B{HpcJaKE_l zZ@99nJUQCz@9tjNTk4j38hu^Jli~+LPrL7hyT#oA;XXhBSRM9(va#J(pRC~bSk>lh zu@g>Y^TT8GuH465@Sfnk;BTP?O%2C4LemV<^BpuKDtZ=>LQTxwG^BKzMwb3v>Exga zQ##v?MtS8*G`Ng`wj|LWu2c9&xRGMYHkGxdg zS)1gS|MITjq>f$H@yf8gmYgRa7L1iA@Jb6@Eo0w_MKYFgI9mn*X2OB@)~9|m@(t&= z5xAapTW#$Y;`9e&+GOV+7Vc1_@e^WkMN7TXXfbEtXR)qqN7|gFjO+u#XW55kM)twM zRy77%DIYp$(n{{jJ$#H!jx6`^fS>}9(u=95Y#XUIU^1E*Ef2w}>5eT}PuMpoiWmn6 zca(P3Yh$GgMIx$n={lWwI>c_PnbwN`0;tdWggv-zaV$v!mPw(-ag;P1CY*y~9R~>q zv0=hl;-F7U#PzF#mS8c=g2q}5WHWhUkhBSq0#c5S-7qKxv=#{FDWH?_iKT$plP?9t z6~{WV#Gzvn%cI5l&48u4{?>`5|5E#Yh2aK;A$v+-$ZmaJ#`6xjk2E^*%*oNwO7p^6 zb-a0&xCj~&wmm~w`w55pV%a?$Ys5~KbbcDkQ)Rh|`bcMo;_UOD$T||}l!4PvXjZOi zt}k^n)VeqHmQF{ncCb<1J=lOd-Ye@%>XTCUh7H_3$1(=NY^Bd^yj%v{HD}pipKmbM z&>m>yeQF5PJp3lENipaCVg;#HrAvO{rl!iE^zmzT_wD3~kDTo1`@yo@7u{57x^iIj zebJi4sDa(EwB;|-74#F!Vw8F9d{* zGstl&6$jaCbU356Wr?;zqfEZt$Q*v;972Hn_6l#_l{Od4R*JQc_gPg z?lebBMNiZNyaakq!hgJCHML*RGrc|S&2mi5=pr4qCRb2tbt70N_fB1$5b8k;LcC;qKv1rDrt841=tH_F3jUt z=ShaLU%-#hFO-fk1ARWJU~~!SIjZgcJQqiL8^{XJMz3kNgjt zhdUJ?T%iYfxc9T5X(Ipb-?lhGL!$EU0#a!H{kb$GD*rAZSv*{f1D5Yz=9nf9x!S%;fFk&(D;bo}p26mY zXE^#dDHor!Q{MG3jjlk}vDG>2ly^4WBKIw)L}cr871uQDPeetiyHX6yLxqHyo4iO`9onJtFa#a0+Hy7elBp4A+9~BOr@7D-6m|o zUGYa0A!IX|IhAySU#NzPJtjqdcMf+&TxTO6_$lD)iaGFqv+#)}ciB@Sb;^8_Wf4cW zNPXWa?4*52y|HETKp(2x??YML`5mb})8|OVFiP{Lu5ynttCxgJCGT3&*A)^sj)^4B z1=R+t-jiuwoisey0w&#u*juIS%ojTj^u=#fXN#bP^TPmViep-g5B>xnF% zZAE%#qM7A;r2219RJ_aVzpaC&8T_|RG$hJ@6Ocmvw|}4^QU05NWbyD=?Y|`@NceJe zJ6rvSNR&-OpUJ17Q7GVS3^Li<^9t$XamL#7iAh$>$6Letw}(K%JFZ?rvN*bR26_^Y z17p?=|693z3TD*k4e%1C;TLdhEUl22S_#Kp{%MQ#MjGZ(E|}tuD*@9kc=Ja`Z>1qo zqf0;v9bNCGAyK2t#mDS-T>U$VfGI+1tmMAqDkb{)IA9k~Ad(}4GbQ85Nd25eKYC(} zdXZ_#=x4EeE_cU5vv9`Oc}F&HKiU~#EHv<%DqyD`VbX{l=HTClIpg0cFN7>m6_A`! zy(5TRL_!Kx;%mTwFePuo)v%T3RI6wZ>Esu8@F0;k!^k=_>7PJS5x}ohJ(l6BQelOCV$0+2jD-HlHy zK4nkN`1HmZ2f+A({{SS%yGWqAjt52jh>yTHmEDF*DIxF8AEsVC-C?RkC@o4IPNymn zr1I=(k-+pIQwB0FwO=Y7X9n(hq=M67=|0uAwO_?xN2R^-K$7CBD-vzz>cMLii!w)_ zQ_wU+^!W}N66GHYNTL4m`)Np&e=HzbaYiyV?@v}IzqPgbvm|P!-K9L|gwv4(Tfk%c z6q9R)$dWV7o(W7+Vv*%5S^sT~EPqO}m5eMO=Ga&gm!TvXS^l1eNkx_dW@uzN=hL}; zVgV_1Y?k>bWg?1!`gk zBFhUqBaC)MmKQK-1V@&`BsFBDBp`)GmUR+Rs1hfPe9_3#$uECo`C^ia0Dh(Fv5YL8 zs@&j^A1x{1JY4~)dTf#o|;oyB4(AJHtZe72Zo(gMpPF0D4IO*rdNoW*Cy zl%8Lea}vEDrQH?1j}*G8x-y*H%Zv|0^>)!XZX#pNWH>1)gV;`4Fk5HR!^wL9Bo8OQ zfKM!(WKYg;5+HGOL-(@C+H7d3O7op4`uDPYTVePeg&})NVAz(uEJts;_|nbeL$LCl z+`w`OE~Dt*V=-%%T`OnnUJ@~4a)qY1G})*OHp{yk>r1#9wA5eXTa86<)7ecfzXZ0M z>zcuvT>cPi81slJX9!_t*yQr4g4EhUrwb}vw2iexjjIQ7*Jq#WiV*o#pZZG6EBoG- zLq20O(B=cZw?$JH9gN+uq=a6kUSQ(I>#xjL$~>`5z_BTKP`g-Mc-T?-`gl|xuE(wz zy;G~jr;tn_ozXsMnjv04gN8)K>jF|})UlO@L=7|n$%@|SC0Bp!PPemlaR-UAIpI-p zO2WmXQJ`Y_yI|L)Q4zQmre|3V_)I2ud(;LfiapPnB*o(SRjhwIo?q&=_+q43;+iKv zWj|uEuzF$h{DmaXNs6xHD24{y|Br@5slI>|s`_uHAyKL?AX&WB*FSmI4{`d9tslOR zM8TAMCRI+qDTz?o+nBsEsBA{Ie~F}-+`lRy-3;pzYKtZuNiR}GiNoo?OGCQVRevCA z9x~GO6B<&0Dy^Dn&@`L5Xp%1Rmpvf=hlY46bZ6Cbv<_=bPE6G5&B4Z4x!$~Lvev9L zrmja*wGzIC@Pm__(ek8z&hjNr42J5pDE*7j8`GuV29vCj=-p>WXlw$vve6z;CFtGz<{iCNuKV~E9Tv*$)dV&=8%S3%PZvGH4JNK}9zAcY19@1-G8UY&qs1qf^n!5;!U%H;l?L?Cx~ zkh++G(~J?&M#8s|LG8!k=lGmQhJc(KslH+)wz%Ek=-(vP+~TH(R@6dnC70r!;X7$CT5}SiFp=}A_|2!$0e3f<*FTnNM#~Y1osGIZ1AexjL%WjkgHGv zQs}DPA`+4*d&`MR+t^uD(VhJAAH#bBNks_1LM_ue8WLrhD9N}=oS#a93Kfl4rCCw+ z^r`g4BsC!-a;mh;7L-X)g&8-^wqTN^CO6|8limwRNTGa7q<5#;7TiQq5yG!fTkv)o zQeIoY>W6F}?@kg@sALkRV1bx}Vag>pJLH+%{3RBjBZ&zSke$)?L;BXVLHc1)Na-$` z*gx-dyE>iGYaN=13O!{a8ofkdHSnTC0Vd=!7U4fZo~6vFT#Z=qy#@z~#&M_J9I}`k`pGN? zOVR^r8Rb*knvq@{auR^##Ub7J#EL`MQ=;^OkgY8e#MJP1WY4EMSq?0E1u8fX0H*D*$&PW+hCeR#Fp?cboB4|oGqm3 zffhX-nU>6UFgG_-lIf1NaKG*T_PfK_BI{V4oS9aKMA#)`!3U>QvEr!FOE@G?0z&gT zB=;ecghRp=f;lAXg-BB!lFe+1k2xf0?6gCY_(7S$=ppPJ&h-~Cf)`h!)3611NFGoK z+T+U9d&41-^ngR6)ZQLn=?=*s03>%v{)kV^Az@EGhlHbB#35M+o012s&nAPcY0c+N5fCDy@=NcaA1kA%3ODQmg_>eixhBvh0jl;_8hBd7a(m@D^aHIj02ga`@L+ zLtA0VQb>eJ)zwJbcEcPtqTZ+=wMJ7M1SPSxkXop)qA=$^2lbsU9&_=ZIR*Et7=0E> zT}9aJ4>kPR1pRS^scSBwcRXk+qr0&i23ys6L~q7-+*@#|ijBvYQ}Cd6Jh<@4eQ!s} zu6I;ySK`qXk4T_9{?HgD=8D%sqfB#!tawCdVxpLKrD9Xk>xGD%Q<7Qzcx1BraTpfw zgDV?>6!$jWTA78{j~x?8(y@z2-;S3TFgy?>1Xunj@Bio`!bUzFElD2U~a&HqB4 zio{0&8m~x1b>J0=oI;G>#B~_cZE~1)pwK7_iK>g0hh0Foa2@^|nxG-KDi7Cf12YK6 z)Wdy#)n>IeE{+Wv7BgH468Un9t5+IuS*bE_Ia(?k6rG4@bww-iA8)*3y4Hf8{WBDu zoV#}02%HLBukNmnmq$%L$%&=ZtU**a0^23`RGT9#4KX=hy=t;jst$wmP=#yy>J7$k zJXn}>cR{t;sEqC^l^dl!mC;fB7k_NjChJ3$l9Y;)!G6U-OY`wun(MMkGddYt9C!YK zpbAbN51wmqs$2)ojSr1Z4p)YOx23W2mGGijs+1eRNqjR}9lw(CE1|Uu;8%l@L$&cH zh(PhN<8U;uHgaA)H7~E`*u2VHU)zltu@bAUPWm;aaMWKQYyC}kc*5unsGD2kI z4NhFRrLE((pZV+qf|t&S z&YRu_9A)W>>;U|F2a7N-E>?=>s|nn7lSAo?GNHE|pIAbVJtfj*%qc5+3GT{Dy$-jg z200tcJkAF1B9=XqE@OzhakOJzmYv2NjycAA7!vYN+v!*jobyL6w9|2_YTFv@nA0JN zNV*-1*w%o}*9=uAFyhPVcWhDEXZAbJg{B$&jsY4HWvc}w=Pc@~1Fw>xOskd6??^2G zPnkyr9ie{5K9UU5T2maGuaqU`djAs%FE`r^cm-xUC-3|--J3{S0(hqK=SzvmJZt z%xrg3y}T!AsyoIr)j|6L^W0L$JjZ&BO>zgymoUSzXM1{kPzX;>t+ABt2(>=&1J$q{P-&_Q3j`Sc|F*tJS80y(ps*y${juitZ5DyPY*t!urJyI1AE>q+^xzdUB5P4Bj|Z>N z%{+_z5}Ib1MGpKjj2myg0`0+bNTIXHp(G@8aArzK753m66~VKJR;1`L6jE#!`3}6x zJB#>+iJU$<=fQKuNInEoG5gP+eD zxDH{ti3F8q_UnZ#t;a6z2 z#P?`Od3D)QE%68mDZgY2R!cY~<6lGiGf72&WP&{_ZIq*{5opY_8iaRwJ*$8@Njh0+ zM{2flK48vDS@72#r~5Vt8t#ki0NfV`+k)MflkS!7OE*3-_k}%q+!sFQ_=Rg=D9io< zL$%ApZYXLz{M(_Pps;(Q!j3&9uxrb9sG~P4F_+@opxDJQ`uCWplx6$V0<#x%iR`fP zl!4Pv;0J(q4~>=^jqVM-rPGHijiJFtb@yOnqC8YtUs9ixx;JbPbr0Y=2~OHm#a3XQ z8R`XBOI{jlXs1=k7!hHbMNg=Yrs<1SOr577wT9c1^VM;Q-u7hjo#ievYHIY8lf7e>%1~Az{WY7Bmgwm<5ed+@3_6 zp;0D#FSj`%G-=JJONp2%KSzkhY0Ay*O(!O|H$7Jz3xs=DhOvk`c(2nN1yq?8v-dhJ zGxj=pVAvao$_&9#$6 z;sLd}xa-MY!c8<~QviV%KNHTckJLFYs~A#pym9 zD^KU+$`iW*MASgxE?6j@EY&8P6O&C|v4HO`xL^z0rws4ms^7h(U6XZqT`x`4YeSVr z15e?U2V1nYPwgT7D@vv-x`osVQ^?Z8`x)|rS2Mg_G^U(nXeL*)Bp1O=bm&EJI_Tp7 zm9J)f0-snqh&?3|F3hi47IBP=tY$6e`#bn5mi7lMKZ{+Eqkrp@TSBZoyN0K=g7UOv z<1}CEPzS)6wC0{*(uwFUPTI>o~&8NHu`dWdaHz7eWtN#*s zm)GjYhlMoxol;b01Yahkl4kFZ#n28E+!e|xvrd1ct@lq5Xjk;GfbCBFnHnLj_x0F< z2VXx_h?7}u8GK1P!FoI77Hqx$3{biC{tG@a>&>2g)|+Eo#Cor^tJO$D&Q3HitgGEL zwjgcymisE{Xbl_ZP#fC1hZV(DANdJnikT_3RB_^K}TrJHb9a=#vK&L9P?)~rM6E0OvcNFh4_k~axF7ZfMP85}CbfV6(itvA(pkRvRt#m$ua>E4^@eTw}6c87w!3s#W#V z+2zp&obbuxU~3az+p8%L`nv5P23J!a9&2c8G+9lFFe&AVtr5;skWzQhvwMZ=jkQsu zHqJH^Id{2W4sIBZ`0dl58Iqb}wsj;!G382ypv%{!izzj6Q4e;*0tQt~*;;5J#tYi4 zcgjGqwV5ZSU_zBux-hXXd|8)ShlL8yF|W%z!r6=X(z?=Zp8Qg-Z|WB|*;`1m$y?LT zg{Cmu*siPpY}WxA5_LVEfE4PARcT0+D<&XWyqtwrhw;&>tP~p}m$vxtHe0VHQOND1 zaZuDU$6fEY>TCP z)LnS8x%*Zc(ycC<-jIu?_tKC8RB6>ry@$3n3ui7#7XQPh?Bg`NQ=v0UTCKwxlM@rQ zdULQbR<1X%nyfV|jj8KVh%4b+B}Ch+Fy$?0jM zVTCx!8Ld$2=j?`6r}LHf61d~-t9ueovA((IG#KE<)&#V;VoQrgi2JmfjOajUlquIB zx3nNM0KpD+PCG;>fpk7ko@Etg3p3`-DwsQ3PEPJ!frNLoeVe+^L;|IOFQ=h`Mb(+ zcwhWk085M8Bbgd6rVS4uv*w9}To*?BjK{D$Cx^E;Wnq<}ChbRu)Ge z!4~|&9VZ8_+Nh}%2~xLaodUV2m=XYaAL81_(2 z)W#do8*r<_cMQYrJxaCq17yw5FL8c;Aum5?gT6cY$;3a|DDMWw?XvWy+9)-uW7W|z zySWHCt3KPYV+T_un~lq zV!S+7S+TyfVpDn7zu&rIpVftMP`P za@vZ05-%aLzw-~0(;+fV@K0$t8^jB~Nqc3OG>L8k#l1dy4g7y=&cxp4NNs#7dL8_= zk8K}*2|Q^Er<<%5BJeF*ed zsks72a>Fdv6Rk43Xr+1x^S%Wrc1gjMvO$>n@T$QJPNHth=d1O}KPSzpq=9*g@R{!0dY61)ib#GgtN*^s#&m}goR zd&tn6D_*49PEWum=}88Bi{ngj#eMu66&goY%#wOY)0-8snd81UKvS@Cp|ugW(U7RP zPe2Nd`#wrTqT)UQ$>Jd^ktgE5WaM!#iGVr3P;pb2wpHwFEuLlDqKSG?DEc0a8N;@ z+$W7kFZhefZ?Zp>G?_!NEfeA*dbto9`J)&7)zl7%UXJvktdQ}40{Ry3(Qk5P{IZ2% zXxnnr)?z3o;un-cprd>m`?PKG%XKkE(ddf!Wgj*QSDLdheqr3_MhogN#NaQNhALB=-$$vdU*osg-VdqFxG-qw9}r>w9MPnA1KJHvT%|`QZHwsq&Y4W1Ua5bK}hwK zk(4w~nIb7^?Ue%Lh@?IOVC5|73C2 zqkEAwzWsNFXbk2|XVG81Z3LG=pkA@mn5Ya@cU6bVXxdAVn#MFWmgqG{fYfGXbQC^p zmPTrO@W;kTd7=V;H&g}Rf(AChPobSE>l-SMV^*H?3HF)}TE!6-sy~ zrtw1;T%ahc-2p|lqtuC_|DKx56^2(R4B1lx!?x_lK4RV?I|^*9cC!8SC8>Q&~dvp29EySuv=$`;4>+MBSU08Z2ssbh?-t&KISa9#%u1TA* ziZ58$d*1j<$dd_mgvQfGSybCg9|SV`zvutPLl*khQs32l6TmH$wMh%&xxjN9iteHBZ8k zCQHAt&DP^-E>UJ{Ei}zwwl>m`D6=IXg_^CW(~u}#6Ob&kb(WGr0Z9oVIS<*LCjrFf z%Q8tvsO?MCRxOIvs3 zGLvo7#I~DAQgXA6MX9zacsmIxlxf#wE+)&WV(RdO8ND&Ff0(2ogjb;^=5sV8%EXY$ z%&dHjs&A37LgkV$15%ke$my{GkC3E<2*_yz4uq_AjA_3kA%!w6smuteoxJiZ^TO|v z9uqZR3Ka`g=A&syxs{nMDa7Q`O~T48m)RWF^ho9@Bn=^294eV}X-Ih`<8wGJBf*6V zCt+#!lf!W(Nll2DoW^Fh%SP`dVdduB{;<(Ekfh{io68!!o`e<3wuF_QR%>uONka&~ zLao8aXh?ajfn)akA_*zCTo|Nw+Gzis2oI1Hgh<8C`THR~I&F~tG;NUPf3K+T5z4(I zi$b!~G34f+jA?|`G-}jv6OcmFaHr9bs5D$gn$Dpi1<+)r;Z$Mf(iT42@#G~mtQ-kA zPOL3)(-=7y8B;%JhjTb<6tFh(#ye*~L<|4PvuU6l0$0aKZ>)hv>^17JK{K!8j zS-N;=q%v0C3UxHW2b;b$rfJr>DXmqpgH6)_TIbe9ug1Q4ImB^T3FdDdQ~w)dNZIQJ z*^V}S74$`wd>CqEt+u`i+GRi5^aaq0A8m?C!;dyiqa92C#M!3ps*qyZg`%YjwNRz; z@Y46fccQ@cMfk`R(kO6Udgf$xw7CX$!Hn}Vzv?*LZ?DR7eLpLU7Ttxtc10f&oy$EQ zwp2}HBrt35U^8gTd+^z@<)NXH1YcuvN`mmN+ z=88V#0)qP6=JjtBzg&for2qFAG|jMJHS<5X9dQqJGK3J2LIbc@-(>P0NI2B_*bk>C21oS zKtOWxcA@6&wiq|hA|dAHrUkLx{PRb~my^^4@XvPL1ID)9z~omfH266;1(p#zSWggm z&ILMsJ&_f{&0M7ldhyXVOjpy?QbAlDnu1~tfV!Rf7&o#NW-L7?*&XdPWN9q z_5Wx{)M|u)6lx6LOhclKp^J~%k2HB7iGZn8lu1iu!Og=R3yi_r0K0f7K#mN~l#C-I z^>Y?9Yu_dM8BWW|t(KPM!4YMJW+Iec+Oj^gRs28NB8^0f*n(I<9N%$>!&DJzcf=M< zC&%(`!KAVat%EIZ*|Wb=qmxK9d;2C^=S zm=(0{OI2G!dV+TnT%?e5hB?%HyA_&(HxWAD?w}!2^R0m7^l}{qM&l$TbBIwBYr>Q> zNCiwdr@|h#CNk25i@ktaZK5qm5QJ{vL}xP6qY8h^*dhH#(GWPVHlx_p)EfyVD}a! zx{4V+U7RZ{o_=AQyAKM9xlXO5|P6$vS~q7|K*ojT?(ncP595yG!fr|AM3QeHdYtSx&62`jg31gz=P z=5dma5a~E=r=xu7IV7aq97`=yA-x^Eb=`=|684O8d>ATzDUEcIvBF`gpcWunK zu*BURB9_jbxRV_~;?BW@;Kbc$Kx#a3_gQ>mi97bxnZ(`E)nRYS?qDNjhX+{A+1i{c zBmZ9yOG3J2Eq#$w40r(Q>14X}LZyTpeoiW283;IiHPUK6iXqZ95Ns z!|m@66(yPN?*q^@gZ=#_4T-Y90+Q4I&Xa73mHPgb1eeD0>-6MF_t_ zlcN$c8?@qN2KiB!?JHzNk??~9N9i`gNs4~=S@Z$O&kXe5r5L(Wun4N?K^mr6<4c7?|S zcTF2;>mHqCTdUgU-ze@RDme`vF5{koO*JI^EHFHL0uK-V&Q|DV4*t%BrWu02Z8Rim zx)P8w1%Eq9aJjv`wgi8I9^0kx2Y*+Sq>xS?#kmDqYxJbR^#6qs7>l)Yu0+`M;j4na>QnLT<@T71n<#tX zw#eG#=rCRcSvI}dA(&<0CQWoy;Y!H?@b2WSvt#?f#NOfZc(XdxhhJ59_vs(EYu9xX ze_IHwwpFdRbO)~BV=>jS-PnUnLZ$m)+A`aD_(QBS+j%g}2PlGcToD82xE`0nNd>Ew z_N9X^t<^pkcQqotGT-iLEiz{2XU0mZ=u#v*W6)%Y&Pr}PB9|K;2u+1qYf7tdYNlS>7Y>VTE^rxbbY&XYbb1XpA6K8Z5 z0!_?!m-o*&;DBqpjdMJ@*O!#Ed&=YEwI=h}``H!Jb+}!+3YWC^pIshpRPd(iUFFHq zW`B40%HC49-2UzBLSAPyP~g6#Ubs5mjRRau4LDSXeb8+Jw$&#q_&wH@`C9C()kgjB z7zA2PW26nqR7F)9i?6M+F0pA zk-REhx=tsn4zb&6rnTa~0P2%59@^qqk_0RhNsHqsX*f(c&y95)Bpk$s31^9eJ}nW~ zuMS#*#V`vRU#P@DHj_uQNt*y^Bjpm=4TI7~Zw9Em#`a(EiKUI$lP_(=6~{Ug%AsQt zOL=%cVEOWI3&+ig&~&Zc-lj0TU17+c5*YsMPJpnCXDD)?9e2djS=m6Thapsg z1Jz-P7LJQsfGf59w^-(ifi(`~BPw+-$K(X>q-RxcsXDyA#N0W z>r3dq!3*K4s&#IC&bRVM#kt@7DpkbSf0%!-ajf{ol~E{^fXWN=CC73*oGUKfVRf!} z9G>9@TNsEx;-7Efa}KY<)kl>hDDju~i|yNi5#S&TXVp4{?v#PkPiR)IX|6AIGtqT# z=q;U&j2&!LcMmouz>cjisZUDX8#eIB1}j5^_Nf8R49Mp}-Avab*f;)atf6grNZ%M? zn#ZlhhgK{u`m};n^ca4r*(|Agzq|{iH4C*!T3r5z&7>bG3|yJPo{=AoJX|p+LP5aD zcfjIl?4yUU8wUFq3icd{6QpcGM)FS^{;yNu|8e9`PWX>{;9DokU;Y#ru74k=&AJ+y z8^`x%7^h;GTBlIY;73f`2TzNaAZ2*61w8*p_9%=ErdvTmWmCb>(|QBE1o_T}rqm*g z989zM=QG&nk%jGCVWI^k)(O_+cG=}L+SJL_%Qzl(7RJAkbuA5vijM`P(D=BYhD623 z0+Pi)mc8_!ne0fTKAl9s)PhXe`qVTkaf9#qOjt3cOqZ_h1DTiyDCH4OcfqBi*2%Kz zr_DA<{*tF~*BBpS#lC)}eI5;oQd$8iRB2y9L!y*cKq{!T|3V^QihkOZ_GTum3`(1k z=N}1Hs=$`OE4aiP13qVaoZNYw0*k*06ckOK6`zFDrjTM{)B9_=~rM>MP) zH_LHi3t62d$!Nr7a#A;9|Ai)wvYmf~risk4-^d*FFzGr_Mn*siH8RK0kSOI4kSrsk zH-o#c6L9UD?j=#kZD!KG8z(Ps;D8rE=S;rbCnp6nUd8cq*buWXc16uJ8POX_Vsf+2VMO0bLJDQu{xqT=Bq<2tRj3jD3=Ju-5oH%p+n&@nNJybl zNtn>k8>X{*1ODLW$0Q*k!U+wte%oe9{#pCLM<~A|gr-o1JCuf$SK&Ms^mr0lZl&8l z7WDBXF(E>7&fE?Qx{-tw%C`M!K`$XG2;o(zLJ!f9@+!2$f?h>J3YE&=fCYUKNl1ur zLM`a4rw!7-OdF)zi$bz2{M6JDNr0D?~QUFcX+WX8N zUZ@TUTzs^Bq(^C3Iab{{v9`obOX19(rhY#1S6`*{S7zxNEhw1BD(&OQ`?YMPWvVs14*S!Fr=s6NJ$Gvk`~k<@O^s~D zYTkPRj)eoSG}o9%ABRSnHuH_liGB>dGH7z+-dTAMBj;;HvRIv;0rN?~2=@-8?$}#< zX1P&;tsLto_O55!7S`|3D;XPi!tRjrQ1jxUk;+(kD{R5yd(v>r!d%f%tCfBQ+$#Ol z_VTPkqE=5PaM7c4w4|fe*fTH5KbAsOBgS@9tcf9HS0DC7zXuqtnG<`bTJt9Mu5s)J zLRI)Vd<4X;gudc+MV7j01+r4LPl9%>xu9GS6<0v#I24wPsa!KLS{?zmB zr>>6{%mpRsf>zN&d_v`n4uYo^O*x`^CKi=1YumOAwo?yE9ACoYtjgo!2vD`}BlL4+;G&BVDr{*Jz~!ba zTjr+31m^8!my`DME@{B&T$08T4qiNzOECg}1Af5i0D=v$UAEjbPWFN=MmQ!b!-_xc z>{9cv%y~GNm50%@u*Grb9|!_)a^T#JKp`gr_I$w(H@NPiGz4Vhv1N@$ZKzrX>Pma6 z&5_b6aE#fmU6nd;1UF~FPEa_RS1qy05~()!sOhh9`p5FpKifzDyv^5?$0kNAs&G`l z(9rjB=-1|jKG%XCz4SC~K`;LRn1&kPW!PWh^G45t68u*k?q4xft6f>GtmtJgj6(nZ z6?jKQeT<(w$G3Nv;S^;28e}*$I>`<~o~T!cP``)SPVPR@kFIL#A7C9Lv~8dSJqQwy zR$hUJU^Is6)d}1P*uP>M>>S7UC~w?FF3?)Z@xtc(Fg?}*1M2F5W8>^%JMT&Al7Uyx zigRJl;PW1>PqmvcI(Z}P?fQ=v}S|R z!8TrqF=Ff#l{^qTMa7@CsBb4tIel>7yHwi_u+!Rd+S=R}mWf&wYcJ#4j6J*RUFM2D zt#4yIg+U&VcX`OKA|^Of7Jg2YJNehR z=lzTaIPMsOOfU*aPTnrmyxkV#=28-3Zf;r-+s!{n!*JV}s3crPQWL;Gorl4!Pr%r= z8<_lxWvK4vnqV2RgY^UfGlLi%Rwi-gD!#)Uvu^Nc8>Xkx)Ka;`v!E&Hr8S7>@X1Ot zSN>_kyp)D{6pXUO4)%qZJ?M%AOgjax;+7ffW7G}PkSJp)AcY#kIt__3hAuv`6%f== zD@`Smic4FL1(Fw%2$)JmnY7#sBq=uRI>0XOR+1xwGbQ85Nd27UZnf_ceGKOTc6Q=c z$bKrH&9XdxDOjJ`Dt=pAq>-3lEQke6;=ek?VXBCqNG@b+F|vPq`D{ z8l6Pq`|TjmOo?xv!eqJcZz5A5Vfb|jUbteg9OEshBfiYFkwZLmBa2WVMiwriN{2aq zQQ8tch?>$B{b#Vkh|FO0PNusI#qW#8@eyW<6dj76aB)hC6rG8~tHeoJb9j8^I)v(X z0Fob*^?Q6`$7Hdm#358H@>(X)Epod0a-FoXfkEEe6vc9>V=oylG+T^D{^+K$~<&>K2Z_mjEbn~xdctY`3Rk!PoW`E)3bo&bc%h2 zpJ$NZ%wb7Q#tHMU!4Q=D_|tK3P#%FQ+bYx;P0HAzQqo*nKQ zhcS=$g(T?QEOdizH%I+7daohL3gKv|rFaJoDX*oNudHQEVDBg4-q zj{V8_#2kC}K6>X#Z`z43hkw|
A56+B~<5`MAgGZk`~z4XhWX$CJnq9IXM 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 Z6Sa!%V;_+A>ryXT;&4_2?9;`m_W{)@rj!5x literal 0 HcmV?d00001 diff --git a/.doctrees/generated/kor.documents.doctree b/.doctrees/generated/kor.documents.doctree new file mode 100644 index 0000000000000000000000000000000000000000..78c942bd8ed77c36387be889a958507e06765bd2 GIT binary patch literal 19314 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 literal 0 HcmV?d00001 diff --git a/.doctrees/generated/kor.encoders.doctree b/.doctrees/generated/kor.encoders.doctree new file mode 100644 index 0000000000000000000000000000000000000000..365445db602043b0cd325bf68942674d04b33b3f GIT binary patch literal 191177 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 literal 0 HcmV?d00001 diff --git a/.doctrees/generated/kor.extraction.doctree b/.doctrees/generated/kor.extraction.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b2f15ed0a3e48661223826b611c36fad3c8d2514 GIT binary patch literal 192538 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 Lsic?{O(ebnO5^k{ literal 0 HcmV?d00001 diff --git a/.doctrees/generated/modules.doctree b/.doctrees/generated/modules.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0af71bf98568ea3e41fd1797561648f63451a555 GIT binary patch literal 2683 zcmZWrO>Y}F5Or)zmSjo(NK+I@+@dJbBxo!ZMGr-LDbS-)9f~4A4go+c_ zJ_KzKDPn-Pu>ZG@yQ`Jt8dz8y4(H>|n<4+|{96q6s=sjJ3L*7sLK)MBaTi06nXJsY z_VHtU@ppU|pNGDsH_ntc<1y?(BNI|F%XNGc!#JsXsobPFf8==PrP1wi(Ggv7^d>$R z{m}8!E55ZA4z7)jX&bwTzw=dcTMOUE$~%rf4BdjlpO4}!^hq0_I0)S)u30!#Qu8<~ z=QIqc_g2nJk9<=62a>rI>rtkta}eTpN7KCi)njF`Snw!=kO_vr%!R3vmMZs;P+v%qB zmz$a-J19MGP1F>kYn0Z@2CQ^?fYS$cMXM-KmE8!o-L*UuFVoovVVspVF_N_W8?Gfa z4@1v!@1LLj)xZiGmeU-PzPB{vDXI7&jHND0Pq@wugH{av(l0K5xO5V~pX_cDZmqFIP|Xxb zgTf)V%*SwIO22ERQ(1}O;@-|Z6XMS>u8nR2SRZ||yK(PiI86ySpd^5gLP9Z&6xGX; zE;-<4Sns2e!b8h5V;Mo$fgEs?I(8Pinb8a62sk7o1;&zGMbQmoT6#k^qOdQ)s1Ymk zg0!pys+B;3a8^^544zaHK&xG<{YF$cUNS>gdE(P4Ulqo2vVF3mNao2~>7=jtc|w?U zbgoh&O_WFLZV)fS5Xm_3pEko|)Toj5qzRv%7w*UD6k<0iZoM#iV(fAn!=t2G z1prOrd5-dUl%ogv<l8yPV*XGfwH1YMC+ll0UQTag6PleAFob^4O zqlH+SsJ(CjLgu9H%{Bqzio}q+aO!Tgrz;}lQYd^N@1Zh@_d}OcblD#zn%V)Vht;}X z5@j-45Akr335s}7_`2DEas?qyUzY`3q+7e1&dm_OD2GJq1vs#t3g>A~xN^R$H{=-b zjK~}mb}86;?ffl#3(h@ck1}QGHQ_mxir{5od3Ec42xraP04!CDdYIjX1Fqkudpq>% zA%d<22c>2bUEztRcF8f6aA%((8gR6W7ymFzR1pc-_I`5)*J#*qq{C_2eE{wLTRGl7W617h5VX>B^W?bvlVQx!mJp_-c z=5wRk!dI%F+!MCi{T++_wb$y<`Hp=IRqN9fe{|ngvxAEmqawpo1AK_#I5SECSmc1a z;^>z~{t?N)kH3NTcxs`6@Hlc+i4ppFJ27^|$E~<3*>Uq201=m|S_77bTGRjOqAll> F{{a2ZEb#yU literal 0 HcmV?d00001 diff --git a/.doctrees/guidelines.doctree b/.doctrees/guidelines.doctree new file mode 100644 index 0000000000000000000000000000000000000000..cfb5d1cc665aaee48b6cca6337631663cb94275d GIT binary patch literal 8020 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 Qnc-5M)}F*nODI(NA9nF~PXGV_ literal 0 HcmV?d00001 diff --git a/.doctrees/prompt.doctree b/.doctrees/prompt.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d431e5cce09c9d895ec6eecdbde1dce4a0b944ec GIT binary patch literal 14213 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 literal 0 HcmV?d00001 diff --git a/.doctrees/schema_serialization.doctree b/.doctrees/schema_serialization.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9af59e6e13502cbe7149a90cb08d029391819255 GIT binary patch literal 18269 zcmeHPU5FgnbskCc*F74Iq+N|ew35r6b*4w2=^4%Jf+83at+lpSTFr))9F~Z2sk-ZS zSM^j^wd+SS<7FV(u*ORY64t#B0YAl$jv*uufq-L^5D4VK!TEteUJ~+@m*gdcU`X2PbtnziQkdR40w&xCg9uv}C8^23J3I))Z7-!>fk8wMXs{n35;5j!M2hV=Td$MK^H z;@PeNjKZFEDK6>h60CFaY=Zf2Jnh&n>+ME$BQ6_Z=-c%u#ENN!=WH{e)yy>322DZsG zugPm0kcnE4b7MLFU!60@TaaUe$YEXEwXPHUtj~gH*5@E1KZn21<8K9jtKf(A1#2CA zco}@K)^cR52}!nQ;+-2e?mT+*=I*1n-r2ozLy*IBog`vG7L+zb<8){}vBL%Uh?M9tCCQ9UVk|FA{tx>`i&pU?Oii{St;5;^J zXnF2-FD@N+oZCUyAmupU^=Z#NWn2=QTnMi}*oq*D4Y8qBZpP&Xa~$1vyHVIP@{$~v z-MY>k#uagVk$0obs3+QtB>ijPJzxt-e=-pMGz}aDxs*cgrO24Cyk3V*p+t8(X)@wWvj<2SyO zkmh4S8Y@!*cOH3}vea<+2<6v~f)KjYarl;h(hfYgy81-Jnk~=NJU6E(xvW7E#IKG6 zs;4gGyZMDcTg)ZWpO^btF}sv$SyTaiKMzP1t-LT1f4&Eb+?5pJ2yjJlW$^0MX%u`< z)&}V`lJJH7UhPu=Eh!f7{q)?_RKks&WRq9R8vfblPNmCyumoDdcAH*hjo0IlYxs7T ztcIP+FDD%|>fm>{Euk589BN>4%YMpSO~9xnqcbyL=P?IIQ;|*)lTwNP(d13r4?>;J z`edwV(&(7YFnENcl=sxAr#wc*q=j+p(CBm>7VJE(R_=M0t3B+{;d6jM%ehx+#cFcI#QpXpIEMLbkY=x@sCoj}$fj)h7MHiKzV6%3_3_pFmws9&H5u$wVARzp z%rpWmk3dcP3eyfy`IPxbS_oCcYxZ4spxrZErrq^eO?wC-qE4@8m={-=NvmA*`*{hy zornz9k_iGT1#3`CHY4X!SwzM zVgD8EqvPTBw)KIuXfa-x*MFYakOfo5$}E>HST65ZY!hm=XsBqFoDfs{BzB5cA+?E7 zAt_F%+|+Y{y2o#OMHp9-m-zsF(^%sd7xD z9nO*$Xkd^u<>UyAB(t>d=pSH1fYXJ6W7rIPdwa)adElS!p3~ifyO2;hr@QB5i(Bj- z^_=`?-0{VURXi}O@hmREbsg&eOKrDeOK0R=iFB5A)ojwvWeqG#XS#4TH`r@Jk(TNl~TwT48*_rYt-~kk8GOG?!Czx7%z&1r@sNA|E<3 zL6mY=eCSA_59H`qx#8zIj(1?YEj(o;Z(e-zKw2LP!WF__KMdZSxV1XC zqZ{x-Y1JqEfO@ien^TBfpKrfN@C8QQEf6}#s2PrkEyh^$$Lq*XJ^%y4_Q=kb|<0+ zy`Nc<8vDu6;(3xkJD|VYHucMmYo_DcZTys*tPg+jz?;0=h=PjyhY27_@6ntj+--^b z2PqCC2T9!1abx5DhUYm_45xWP#r-=I^XyEPY^wtF`L0P0-6-zzXdJ97lTtQVeMB z5%u6-$zA`q!tYK0WoKT5Nv{OK6nAo^$r}y_nqdFP)jPuC{+N%yb*) z*+c;04=3#(4+AuTKWA3;=S+|G=j3P48G+fQ>B|V&ff13!AL0Hh<9~Rl8Fyp^2s1-W zU=|C6Ak2X2h=a`nf-)b**5m*S*UJA$s3fmBx$EviZfbekQ0i3X|91h>$h!|k1>O7L z7C0`LCDGuQ-}xjosCELb!)oRKK+vG|_jbZ~#p_$b1oIG1_++)ky{ z4cE78udl;DT$h1-@N~f$9&% z%xxU$kQu`X>7{%VFQz;a*KM#ub?9~VF1p;TZNhv^HOK!coKkPsCScft%CPwp7?zuTIKxK72**2|V>Kk$R4Z>rErw?*ik7^2 zD+`x|P3Iv0LJMsK;TkQkR#|;qp}6%55=AJtX!&`es673_^YHX1Kjl3A<6*2Ai>Dlj z;OQTwfcgThi#ArVoY`FW-(L|I#3bB$g@TP%GAAR-D}wkdYuZYBo2F{2fE$Z`-n_MP zymu@~{z74@4EP6H^Ywd@3dQSB)%w@C9KssWyAI5dp^x9zzZago1;nfEzdwn=r4B?* zr?*WcQqW8rVkYsreYO2}qY=zMsHnLg3mkAAvB^lB6VS4C;->c3DYpxz{(p{mF#oRs zfHJWuSo9O9g7c~>Kw?iZYb5{jp0W$ecqUcwo`&1bB>FoEI_7uvOpByf_sWAK5r>8x zxi`GJcE_^K{Jk>};hw9C(?bY?yUVCl*7x1s9y`?pgE5o}|s2&v1 zQwl3*l?*&ZnHyT&L8}Nhr|55A!XzbD-QM0_1>mh)+gnK^gG~saZ-`zbECNDrd=)av3n5{f5Ya z2(`YH0_s!inc9AP47Cl(?$g;^(sPQN)V2)Hi(f2ImBck#)%AOFokeOxaa;d3EL5pq zTPHOCLQ1M<(TNflFfXI|v+Kk~RVS8D(22R(Go6^t9xr9CE0HUm1tkq=DugA;2q2kX zoP+zaaI&mRzgQ7?(w^qc$@anwlmg9DZ_f=B`doxenwf2_(P?xhzR-w#%Hftdj=S-B zStByHG=Ac+#nko3m%4 z7xGx6u(^I~J+Sfn6}3@kzVG?Eg@e#Rnk^3@v>S*eToNICIVdw6N-w@vXeoeb{|0tw zd_lm?aFC;4Q5y<_zVHAb!bb4bL}qlfgG&Vj7zh zb{470O)L`>u}vM0f~I}g!zTnT7*XiySyg=2hEOeHIWEi^ZeFEFTO%OIRfaZ zlS{|Jj-$kA)?NSn=4+tm1;5!SfTx-a{Lf49bYCNp-DiHyW?_@hfo;EGg&hZzl|rMA zU1Ww<@BVyz4g0O5r`t1KfG%>gKZ-8~M~G!R)GfPZIrxM8PSYi^7oQJ01~%H)Bkbz{ zgnEgWMNvmWx{;9f8cas=b24A-H&B_A5To~_Zto-hF%15Ni$o861nKb_l#H4whRdWX zf~c-buR?dbSm2Xf6xQ+zAFlzegn zQtC8?KKm#>$K0p%v5R?2z9I!50?J-nu0(eDqU2?tg@RUp(WZ_@&PNSHor>0CdRwQG8jUf%q;6eM6*g z1??YTx`FuqnD8LRH0AJkmedf4jJ*0esuaJg?LBmD|0?}=5qF*TBK`MOD!$8Ml&CM= zIyujH?_J(=m-pI@tj_^A4!}CkM_V8Bq5Q%X#f$k3!)IS?*w}U?3BX9ykY1Gigv8`) zL_e?)8?00JoOBQJt}hoV)7~WoVoA=*2VGX+0aT`sGx4>-p-1w3_dp1>0>n5kA7; ScrDsEWs}aAL=_8jr}jU}>Zfl2 literal 0 HcmV?d00001 diff --git a/.doctrees/tutorial.doctree b/.doctrees/tutorial.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ba98179074c074bdbef0734d12af1c1320dfc28f GIT binary patch literal 21014 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 literal 0 HcmV?d00001 diff --git a/.doctrees/type_descriptors.doctree b/.doctrees/type_descriptors.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e47da9764b4228e2f482da8291fdcb25fc435338 GIT binary patch literal 18480 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 JstH}%{{=?CsM(HN4=k^JtsNhx$0NrL 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 KN_U|_RsKJDIjEul literal 0 HcmV?d00001 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 0000000..39634f6 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,324 @@ + + + + + + + + Overview: module code — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Toggle navigation sidebar
+ + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+ +
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/adapters.html b/_modules/kor/adapters.html new file mode 100644 index 0000000..d1c8830 --- /dev/null +++ b/_modules/kor/adapters.html @@ -0,0 +1,539 @@ + + + + + + + + kor.adapters — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.adapters

+"""Adapters to convert from validation frameworks to Kor internal representation."""
+import enum
+from typing import (
+    Any,
+    Dict,
+    List,
+    Optional,
+    Sequence,
+    Tuple,
+    Type,
+    Union,
+    get_args,
+    get_origin,
+)
+
+from pydantic import BaseModel
+
+from ._pydantic import PYDANTIC_MAJOR_VERSION
+from .nodes import Bool, ExtractionSchemaNode, Number, Object, Option, Selection, Text
+from .validators import PydanticValidator, Validator
+
+# Not going to support dicts or lists since that requires recursive checks.
+# May make sense to either drop the internal representation, or properly extend it
+# to handle Lists, Unions etc.
+# Not worth the effort, until it's clear that folks are using this functionality.
+PRIMITIVE_TYPES = {str, float, int, type(None)}
+
+
+def _is_many(annotation: Any) -> bool:
+    """Determine if the given annotation should map to field many.
+
+    Map to field many if the annotation is a list or a Union where at least one
+    of the arguments is a list type.
+
+    Args:
+        annotation: The annotation to check.
+
+    Returns:
+        bool
+    """
+    origin = get_origin(annotation)
+    if origin is Union:
+        for arg in get_args(annotation):
+            arg_origin = get_origin(arg)
+            if isinstance(arg_origin, type) and issubclass(arg_origin, List):
+                return True
+    if isinstance(origin, type) and issubclass(origin, List):
+        return True
+    return False
+
+
+def _unpack_if_optional_equivalent(annotation: Any) -> Tuple[bool, Any]:
+    """Determine if type is equivalent to an Optional and if so return the inner type.
+
+    Args:
+        annotation: The annotation to check.
+
+    Returns:
+        Tuple[bool, Any]; e.g., Optional[str] -> (True, str)
+    """
+    origin = get_origin(annotation)
+    if origin is Union:
+        args = get_args(annotation)
+        if len(args) == 2 and type(None) in args:
+            if args[0] is type(None):
+                return True, args[1]
+            else:
+                return True, args[0]
+
+    if origin is Optional:
+        return True, get_args(annotation)[0]
+
+    return False, None
+
+
+def _translate_pydantic_to_kor(
+    model_class: Type[BaseModel],
+    *,
+    name: Optional[str] = None,
+    description: str = "",
+    examples: Sequence[Tuple[str, Dict[str, Any]]] = tuple(),
+    many: bool = False,
+) -> Object:
+    """Convert a pydantic model to Kor internal representation.
+
+    Args:
+        model_class: The pydantic model class to convert.
+        name: The name of the model.
+        description: The description of the model.
+        examples: A sequence of examples of the model.
+        many: Whether the model is a list of models.
+
+    Returns:
+        The Kor internal representation of the model.
+    """
+
+    attributes: List[Union[ExtractionSchemaNode, Selection, "Object"]] = []
+
+    if PYDANTIC_MAJOR_VERSION == 1:
+        fields_info = model_class.__fields__.items()  # type: ignore[attr-defined]
+    else:
+        fields_info = model_class.model_fields.items()  # type: ignore[attr-defined]
+
+    for field_name, field in fields_info:
+        if PYDANTIC_MAJOR_VERSION == 1:
+            field_info = field.field_info
+            extra = field_info.extra
+            field_examples = extra.get(  # type: ignore[attr-defined]
+                "examples", tuple()
+            )
+            field_description = getattr(field_info, "description") or ""
+            type_ = field.outer_type_
+        else:
+            type_ = field.annotation
+            field_examples = field.examples or tuple()  # type: ignore[attr-defined]
+            field_description = getattr(field, "description") or ""
+
+        field_many = _is_many(type_)
+
+        attribute: Union[ExtractionSchemaNode, Selection, "Object"]
+
+        is_optional_equivalent, unpacked_optional = _unpack_if_optional_equivalent(
+            type_
+        )
+
+        if get_origin(type_) is Union and not is_optional_equivalent:
+            # Verify that all arguments are primitive types
+            args = get_args(type_)
+
+            if not all(arg in PRIMITIVE_TYPES for arg in args):
+                raise NotImplementedError(
+                    "Union of non-primitive types not supported. Issue with"
+                    f"field: `{field_name}`. Has type: `{type_}`"
+                )
+
+            attribute = Text(
+                id=field_name,
+                examples=field_examples,
+                description=field_description,
+                many=field_many,
+            )
+        else:
+            # If the type is an Optional or Union equivalent, use the inner type
+            type_to_use = unpacked_optional if is_optional_equivalent else type_
+
+            # If the type is a parameterized generic, we want to extract
+            # the inner type; e.g., List[str] -> str
+            if not isinstance(type_to_use, type):  # i.e., parameterized generic
+                origin_ = get_origin(type_to_use)
+                if not isinstance(origin_, type) or not issubclass(origin_, List):
+                    raise NotImplementedError(f"Unsupported type: {type_to_use}")
+                type_to_use = get_args(type_to_use)[0]  # extract the argument
+
+            if issubclass(type_to_use, BaseModel):
+                attribute = _translate_pydantic_to_kor(
+                    type_to_use,
+                    description=field_description,
+                    examples=field_examples,
+                    many=field_many,
+                    name=field_name,
+                )
+            # Precedence matters here since bool is a subclass of int
+            elif issubclass(type_to_use, bool):
+                attribute = Bool(
+                    id=field_name,
+                    examples=field_examples,
+                    description=field_description,
+                    many=field_many,
+                )
+            elif issubclass(type_to_use, (int, float)):
+                attribute = Number(
+                    id=field_name,
+                    examples=field_examples,
+                    description=field_description,
+                    many=field_many,
+                )
+            elif issubclass(type_to_use, enum.Enum):
+                enum_choices = list(type_to_use)
+                attribute = Selection(
+                    id=field_name,
+                    description=field_description,
+                    many=field_many,
+                    examples=field_examples,
+                    options=[Option(id=choice.value) for choice in enum_choices],
+                )
+            else:
+                attribute = Text(
+                    id=field_name,
+                    examples=field_examples,
+                    description=field_description,
+                    many=field_many,
+                )
+
+        attributes.append(attribute)
+
+    return Object(
+        id=name or model_class.__name__.lower(),
+        attributes=attributes,
+        description=description,
+        examples=examples,
+        many=many,
+    )
+
+
+# PUBLIC API
+
+
+
[docs]def from_pydantic( + model_class: Type[BaseModel], + *, + description: str = "", + examples: Sequence[Tuple[str, Dict[str, Any]]] = tuple(), + many: bool = False, +) -> Tuple[Object, Validator]: + """Convert a pydantic model to Kor internal representation. + + Args: + model_class: The pydantic model class to convert. + description: The description of the model. + examples: A sequence of examples to be used for the model. + many: Whether to expect the model to be a list of models. + + Returns: + A tuple of the Kor internal representation of the model and a validator. + """ + schema = _translate_pydantic_to_kor( + model_class, + description=description, + examples=examples, + many=many, + ) + validator = PydanticValidator(model_class, schema.many) + return schema, validator
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/documents/html.html b/_modules/kor/documents/html.html new file mode 100644 index 0000000..3a1fb17 --- /dev/null +++ b/_modules/kor/documents/html.html @@ -0,0 +1,391 @@ + + + + + + + + kor.documents.html — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.documents.html

+"""Load and chunk HTMLs with potential pre-processing to clean the html."""
+
+import re
+from typing import Tuple
+
+from langchain.schema import Document
+
+from kor.documents.typedefs import AbstractDocumentProcessor
+
+# Regular expression pattern to detect multiple new lines in a row with optional
+# whitespace in between
+CONSECUTIVE_NEW_LINES = re.compile(r"\n(\s*\n)+", flags=re.UNICODE)
+
+
+def _get_mini_html(html: str, *, tags_to_remove: Tuple[str, ...] = tuple()) -> str:
+    """Clean up HTML tags."""
+    try:
+        from bs4 import BeautifulSoup
+    except ImportError:
+        raise ImportError(
+            "Please install BeautifulSoup to use the HTML document processor. "
+            "You can do so by running `pip install beautifulsoup4`."
+        )
+    # Parse the HTML document using BeautifulSoup
+    soup = BeautifulSoup(html, "html.parser")
+
+    # Remove all CSS stylesheets
+    for stylesheet in soup.find_all("link", rel="stylesheet"):
+        stylesheet.extract()
+
+    for tag_to_remove in tags_to_remove:
+        # Remove all matching tags
+        for tag in soup.find_all(tag_to_remove):
+            tag.extract()
+
+    new_html = repr(soup)
+    return new_html
+
+
+def _clean_html(html: str, *, tags_to_remove: Tuple[str, ...] = tuple()) -> str:
+    """Clean up HTML and convert to markdown using markdownify."""
+    try:
+        import markdownify
+    except ImportError:
+        raise ImportError(
+            "Please install markdownify to use the HTML document processor. "
+            "You can do so by running `pip install markdownify`."
+        )
+
+    html = _get_mini_html(html, tags_to_remove=tags_to_remove)
+    md = markdownify.markdownify(html)
+    return CONSECUTIVE_NEW_LINES.sub("\n\n", md).strip()
+
+
+## PUBLIC API
+
+
+
[docs]class MarkdownifyHTMLProcessor(AbstractDocumentProcessor): + """A preprocessor to clean HTML and convert to markdown using markdownify.""" + + def __init__( + self, + tags_to_remove: Tuple[str, ...] = ("svg", "img", "script", "style"), + ) -> None: + """Initialize the preprocessor. + + Args: + tags_to_remove: A tuple of tags to remove from the HTML + """ + self.tags_to_remove = tags_to_remove + +
[docs] def process(self, document: Document) -> Document: + """Clean up HTML and convert to markdown using markdownify. + + Args: + document: a document with HTML content + + Returns: + The cleaned HTML + """ + new_document = document.copy() + new_document.page_content = _clean_html( + document.page_content, tags_to_remove=self.tags_to_remove + ) + return new_document
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/documents/typedefs.html b/_modules/kor/documents/typedefs.html new file mode 100644 index 0000000..9967912 --- /dev/null +++ b/_modules/kor/documents/typedefs.html @@ -0,0 +1,318 @@ + + + + + + + + kor.documents.typedefs — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.documents.typedefs

+import abc
+
+from langchain.schema import Document
+
+
+
[docs]class AbstractDocumentProcessor(abc.ABC): + """An interface for document transformers.""" + +
[docs] @abc.abstractmethod + def process(self, document: Document) -> Document: + """Process document.""" + raise NotImplementedError()
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/csv_data.html b/_modules/kor/encoders/csv_data.html new file mode 100644 index 0000000..50f2308 --- /dev/null +++ b/_modules/kor/encoders/csv_data.html @@ -0,0 +1,445 @@ + + + + + + + + kor.encoders.csv_data — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.csv_data

+"""Module that contains Kor flavored encoders/decoders for CSV data.
+
+The code will need to eventually support handling some form of nested objects,
+via either JSON encoded column values or by breaking down nested attributes
+into additional columns (likely both methods).
+"""
+
+from io import StringIO
+from typing import Any, Dict, List
+
+import pandas as pd
+
+from kor.encoders.typedefs import SchemaBasedEncoder
+from kor.encoders.utils import unwrap_tag, wrap_in_tag
+from kor.exceptions import ParseError
+from kor.nodes import AbstractSchemaNode, Object
+
+DELIMITER = "|"
+
+
+def _extract_top_level_fieldnames(node: AbstractSchemaNode) -> List[str]:
+    """Temporary schema description for CSV extraction."""
+    if isinstance(node, Object):
+        return [attributes.id for attributes in node.attributes]
+    else:
+        return [node.id]
+
+
+# PUBLIC API
+
+
+
[docs]class CSVEncoder(SchemaBasedEncoder): + """CSV encoder.""" + + def __init__(self, node: AbstractSchemaNode, use_tags: bool = False) -> None: + """Attach node to the encoder to allow the encoder to understand schema. + + Args: + node: The schema node to attach to the encoder. + use_tags: Whether to wrap the output in tags. This may help identify + the table content in cases when the model attempts to add + clarifying explanations. + """ + super().__init__(node) + self.use_tags = use_tags + + # Verify that if we have an Object then none of its attributes are lists + # or objects as that functionality is not yet supported. + if isinstance(node, Object): + for attribute in node.attributes: + if attribute.many or isinstance(attribute, Object): + raise NotImplementedError( + "CSV Encoder does not yet support embedded lists or " + f"objects (attribute `{attribute.id}`)." + ) + +
[docs] def encode(self, data: Any) -> str: + """Encode the data.""" + if not isinstance(data, dict): + raise TypeError(f"Was expecting a dictionary got {type(data)}") + + expected_key = self.node.id + + if expected_key not in data: + raise AssertionError(f"Expected a key: `{expected_key} to appear in data.") + + if isinstance(self.node, Object): + field_names = _extract_top_level_fieldnames(self.node) + else: + field_names = [self.node.id] + + data_to_output = data[expected_key] + + if not isinstance(data_to_output, list): + # Should always output records for pd.Dataframe + data_to_output = [data_to_output] + table_content = pd.DataFrame(data_to_output, columns=field_names).to_csv( + index=False, sep=DELIMITER + ) + + if self.use_tags: + return wrap_in_tag("csv", table_content) + + return table_content
+ +
[docs] def decode(self, text: str) -> Dict[str, List[Dict[str, Any]]]: + """Decode the text.""" + # First get the content between the table tags + if self.use_tags: + table_str = unwrap_tag("csv", text) + else: + table_str = text + + if table_str: + with StringIO(table_str) as buffer: + try: + df = pd.read_csv( + buffer, + dtype=str, + keep_default_na=False, + sep=DELIMITER, + skipinitialspace=True, + ) + except Exception as e: + raise ParseError(e) + + records = df.to_dict(orient="records") + else: + records = [] + + namespace = self.node.id + return {namespace: records}
+ +
[docs] def get_instruction_segment(self) -> str: + """Format instructions.""" + instructions = [ + "Please output the extracted information in CSV format in Excel dialect.", + f"Please use a {DELIMITER} as the delimiter." + # TODO(Eugene): Add this when we start supporting embedded columns. + # "If a column corresponds to an array or an object, + # use a JSON encoding to " + # "encode its value.", + ] + + if self.use_tags: + instructions.append( + "Please output a <csv> tag before and a closing </csv> after the table." + ) + + instructions.extend( + [ + "\n", + "Do NOT add any clarifying information.", + "Output MUST follow the schema above.", + "Do NOT add any additional columns that do not appear in the schema.", + ] + ) + + return " ".join(instructions)
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/encode.html b/_modules/kor/encoders/encode.html new file mode 100644 index 0000000..49c0351 --- /dev/null +++ b/_modules/kor/encoders/encode.html @@ -0,0 +1,411 @@ + + + + + + + + kor.encoders.encode — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.encode

+from typing import Any, Callable, List, Literal, Mapping, Sequence, Tuple, Type, Union
+
+from kor.nodes import AbstractSchemaNode
+
+from .csv_data import CSVEncoder
+from .json_data import JSONEncoder
+from .typedefs import Encoder, SchemaBasedEncoder
+from .xml import XMLEncoder
+
+_ENCODER_REGISTRY: Mapping[str, Type[Encoder]] = {
+    "csv": CSVEncoder,
+    "xml": XMLEncoder,
+    "json": JSONEncoder,
+}
+
+# Use to denote different types of formatters for the input.
+InputFormatter = Union[
+    Literal["text_prefix"], Literal["triple_quotes"], None, Callable[[str], str]
+]
+
+
+# PUBLIC API
+
+
+
[docs]def format_text(text: str, input_formatter: InputFormatter = None) -> str: + """An encoder for the input text. + + Args: + text: the text to encode + input_formatter: the formatter to use for the input + * None: use for single sentences or single paragraphs, no formatting + * triple_quotes: surround input with \"\"\", use for long text + * text_prefix: same as triple_quote but with `TEXT: ` prefix + * Callable: user provided function + + Returns: + The encoded text if it was encoded + """ + if input_formatter == "text_prefix": + return 'Text: """\n' + text + '\n"""' + elif input_formatter == "triple_quotes": + return '"""\n' + text + '\n"""' + elif input_formatter is None: + return text + else: + raise NotImplementedError( + f'No support for input encoding "{input_formatter}". ' + ' Use one of "long_text" or None.' + )
+ + +
[docs]def encode_examples( + examples: Sequence[Tuple[str, str]], + encoder: Encoder, + input_formatter: InputFormatter = None, +) -> List[Tuple[str, str]]: + """Encode the output using the given encoder.""" + + return [ + ( + format_text(input_example, input_formatter=input_formatter), + encoder.encode(output_example), + ) + for input_example, output_example in examples + ]
+ + +
[docs]def initialize_encoder( + encoder_or_encoder_class: Union[Type[Encoder], Encoder, str], + schema: AbstractSchemaNode, + **kwargs: Any, +) -> Encoder: + """Flexible way to initialize an encoder, used only for top level API. + + Args: + encoder_or_encoder_class: Either an encoder instance, an encoder class + or a string representing the encoder class. + schema: The schema to use for the encoder. + **kwargs: Keyword arguments to pass to the encoder class. + + Returns: + An encoder instance + """ + if isinstance(encoder_or_encoder_class, str): + encoder_name = encoder_or_encoder_class.lower() + if encoder_name not in _ENCODER_REGISTRY: + raise ValueError( + f"Unknown encoder {encoder_name}. " + f"Use one of {sorted(_ENCODER_REGISTRY)}" + ) + encoder_or_encoder_class = _ENCODER_REGISTRY[encoder_name] + if isinstance(encoder_or_encoder_class, type(Encoder)): + if issubclass(encoder_or_encoder_class, SchemaBasedEncoder): + return encoder_or_encoder_class(schema, **kwargs) + else: + return encoder_or_encoder_class(**kwargs) + elif isinstance(encoder_or_encoder_class, Encoder): + if kwargs: + raise ValueError("Unable to use kwargs with an encoder instance") + return encoder_or_encoder_class + else: + raise TypeError( + "Expected str, an encoder or encoder class, got" + f" {type(encoder_or_encoder_class)}" + )
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/json_data.html b/_modules/kor/encoders/json_data.html new file mode 100644 index 0000000..9095bbd --- /dev/null +++ b/_modules/kor/encoders/json_data.html @@ -0,0 +1,416 @@ + + + + + + + + kor.encoders.json_data — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.json_data

+"""JSON encoder and decoder."""
+import json
+from typing import Any
+
+from kor.exceptions import ParseError
+
+from .typedefs import Encoder
+from .utils import unwrap_tag, wrap_in_tag
+
+
+
[docs]class JSONEncoder(Encoder): + """JSON encoder and decoder. + + The encoder by default adds additional <json> tags around the JSON output, + + Additional tags are added to the output to help identify the JSON content + within the LLM response and extract it. + + The usage of <json> tags is similar to the usage of ```JSON and ``` marks. + + Examples: + + .. code-block:: python + + from kor import JSONEncoder + + json_encoder = JSONEncoder(use_tags=True) + data = {"name": "Café"} + json_encoder.encode(data) + # '<json>{"name": "Café"}</json>' + + json_encoder = JSONEncoder(use_tags=True, ensure_ascii=True) + data = {"name": "Café"} + json_encoder.encode(data) + # '<json>{"name": "Caf\\u00e9"}</json>' + + """ + + def __init__(self, use_tags: bool = True, ensure_ascii: bool = False) -> None: + """Initialize the JSON encoder. + + Args: + use_tags: Whether to wrap the output in a special JSON tags. + This may help identify the JSON content in cases when + the model attempts to add clarifying explanations. + ensure_ascii: Whether to escape non-ASCII characters. + Default is False to preserve non-ASCII characters as + that it a more sensible behavior for the extraction + use cases. + """ + self.use_tags = use_tags + self.ensure_ascii = ensure_ascii + +
[docs] def encode(self, data: Any) -> str: + """Encode the data as JSON. + + Args: + data: JSON serializable data. + + Returns: + The JSON encoded data as a string optionally wrapped in <json> tags. + """ + content = json.dumps(data) + if self.use_tags: + return wrap_in_tag("json", json.dumps(data, ensure_ascii=self.ensure_ascii)) + return content
+ +
[docs] def decode(self, text: str) -> Any: + """Decode the text as JSON. + + If the encoder is using tags, the <json> content is identified within the text + and then is decoded. + + Args: + text: the text to be decoded + + Returns: + The decoded JSON data. + """ + if self.use_tags: + content = unwrap_tag("json", text) + else: + content = text + + if content is None: + return {} + try: + return json.loads( + content, + ) + except json.JSONDecodeError as e: + raise ParseError(e)
+ +
[docs] def get_instruction_segment(self) -> str: + """Get the format instructions for the given decoder. + + This is a specification to the LLM that tells it how to shape its response + so that the response can be structured properly using the given decoder. + """ + format_instructions = ( + "Please output the extracted information in JSON format. Do not output" + " anything except for the extracted information. Do not add any clarifying" + " information. Do not add any fields that are not in the schema. If the" + " text contains attributes that do not appear in the schema, please ignore" + " them. All output must be in JSON format and follow the schema specified" + " above." + ) + if self.use_tags: + format_instructions += " Wrap the JSON in <json> tags." + return format_instructions
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/typedefs.html b/_modules/kor/encoders/typedefs.html new file mode 100644 index 0000000..c4c903c --- /dev/null +++ b/_modules/kor/encoders/typedefs.html @@ -0,0 +1,357 @@ + + + + + + + + kor.encoders.typedefs — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.typedefs

+"""Type-definitions for encoders.
+
+This file only contains the interface for encoders.
+
+* Added a pre-built format instruction segment.
+* May remove it at some point later or modify it if we discover that
+  there are many ways of phrasing the format instructions.
+"""
+import abc
+from typing import Any
+
+from kor.nodes import AbstractSchemaNode
+
+
+
[docs]class Encoder(abc.ABC): + """Abstract interface for an encoder. + + The encoder is responsible for encoding and decoding the Output + portion of examples provided to the LLM. + + It must implement a method called get_instruction_segment that + contains instructions for the LLM on how to format its output. + """ + +
[docs] @abc.abstractmethod + def encode(self, data: Any) -> str: + """Encode the data."""
+ +
[docs] @abc.abstractmethod + def decode(self, text: str) -> Any: + """Decode the text."""
+ +
[docs] @abc.abstractmethod + def get_instruction_segment(self) -> str: + """Get the format instructions for the given decoder. + + Used to guide the LLM on how to format its output. + """ + raise NotImplementedError()
+ + +
[docs]class SchemaBasedEncoder(Encoder, abc.ABC): + """Abstract interface for an encoder that has the data schema. + + Inherit from this encoder if the encoder needs to know the schema + of the data that's being encoded. + """ + + def __init__(self, node: AbstractSchemaNode, **kwargs: Any) -> None: + """Attach node to the encoder to allow the encoder to understand schema.""" + self.node = node
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/utils.html b/_modules/kor/encoders/utils.html new file mode 100644 index 0000000..d225369 --- /dev/null +++ b/_modules/kor/encoders/utils.html @@ -0,0 +1,326 @@ + + + + + + + + kor.encoders.utils — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.utils

+import re
+from typing import Optional
+
+# PUBLIC API
+
+
+
[docs]def wrap_in_tag(tag_name: str, content: str) -> str: + """Wrap the content in an HTML style tag.""" + return f"<{tag_name}>{content}</{tag_name}>"
+ + +
[docs]def unwrap_tag(tag_name: str, text: str) -> Optional[str]: + """Extract content located inside a tag.""" + pattern = f"<{tag_name}>(.*?)</{tag_name}>" + content = re.compile(pattern, re.DOTALL) + match = content.search(text) + if match: + return match.group(1) + else: + return None
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/encoders/xml.html b/_modules/kor/encoders/xml.html new file mode 100644 index 0000000..180b711 --- /dev/null +++ b/_modules/kor/encoders/xml.html @@ -0,0 +1,474 @@ + + + + + + + + kor.encoders.xml — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.encoders.xml

+from collections import defaultdict
+from html.parser import HTMLParser
+from typing import Any, DefaultDict, Dict, List, Mapping, Optional, Sequence, Union
+
+from kor.encoders.typedefs import Encoder
+
+LiteralType = Union[str, int, float]
+
+
+def _write_literal(tag_name: str, value: LiteralType) -> str:
+    """Write literal."""
+    return f"<{tag_name}>{value}</{tag_name}>"
+
+
+def _write_list(tag_name: str, values: Sequence[LiteralType]) -> str:
+    """Write list."""
+    return "".join(_write_tag(tag_name, value) for value in values)
+
+
+def _write_dict(tag_name: str, data: Mapping[str, Any]) -> str:
+    """Write a dict."""
+    s_data = "".join(
+        [
+            _write_tag(key, value)
+            for key, value in sorted(data.items(), key=lambda item: item[0])
+        ]
+    )
+    return _write_tag(tag_name, s_data)
+
+
+def _write_tag(
+    tag_name: str, data: Union[LiteralType, Sequence[LiteralType], Mapping[str, Any]]
+) -> str:
+    """Write a tag."""
+    # Dispatch based on type.
+    if isinstance(data, (str, int, float)):
+        return _write_literal(tag_name, data)
+    elif isinstance(data, list):
+        return _write_list(tag_name, data)
+    elif isinstance(data, dict):
+        return _write_dict(tag_name, data)
+    else:
+        raise NotImplementedError(f"No support for {tag_name}")
+
+
+
[docs]class TagParser(HTMLParser): + def __init__(self) -> None: + """A heavy-handed solution, but it's fast for prototyping. + + Might be re-implemented later to restrict scope to the limited grammar, and + more efficiency. + + Uses an HTML parser to parse a limited grammar that allows + for syntax of the form: + + INPUT -> JUNK? VALUE* + JUNK -> JUNK_CHARACTER+ + JUNK_CHARACTER -> whitespace | , + VALUE -> <IDENTIFIER>DATA</IDENTIFIER> | OBJECT + OBJECT -> <IDENTIFIER>VALUE+</IDENTIFIER> + IDENTIFIER -> [a-Z][a-Z0-9_]* + DATA -> .* + + Interprets the data to allow repetition of tags and recursion + to support representation of complex types. + + ^ Just another approximately wrong grammar specification. + """ + super().__init__() + + self.parse_data: DefaultDict[str, List[Any]] = defaultdict(list) + self.stack: List[DefaultDict[str, List[str]]] = [self.parse_data] + self.success = True + self.depth = 0 + self.data: Optional[str] = None + +
[docs] def handle_starttag(self, tag: str, attrs: Any) -> None: + """Hook when a new tag is encountered.""" + self.depth += 1 + self.stack.append(defaultdict(list)) + self.data = None
+ +
[docs] def handle_endtag(self, tag: str) -> None: + """Hook when a tag is closed.""" + self.depth -= 1 + top_of_stack = dict(self.stack.pop(-1)) # Pop the dictionary we don't need it + + # If a lead node + is_leaf = self.data is not None + # Annoying to type here, code is tested, hopefully OK + value = self.data if is_leaf else top_of_stack + # Difficult to type this correctly with mypy (maybe impossible?) + # Can be nested indefinitely, so requires self referencing type + self.stack[-1][tag].append(value) # type: ignore + # Reset the data so we if we encounter a sequence of end tags, we + # don't confuse an outer end tag for belonging to a leaf node. + self.data = None
+ +
[docs] def handle_data(self, data: str) -> None: + """Hook when handling data.""" + # The only data that's allowed is whitespace or a comma surrounded by whitespace + if self.depth == 0 and data.strip() not in (",", ""): + # If this is triggered the parse should be considered invalid. + self.success = False + self.data = data
+ + +# PUBLIC API + + +
[docs]class XMLEncoder(Encoder): + """Experimental XML encoder to encode and decode data. + + .. warning:: + This encoder is not recommended for usage, at least not without further + benchmarking for your use-case. + + The decoder re-interprets all data types as lists, which makes validating + and using parser results more involved. It's unclear whether the encoder + offers more advantages over other encoders (e.g., JSON or CSV). + + The encoder would encode the following dictionary + + .. code-block:: JSON + + { + "color": ["red", "blue"], + "height": ["6.1"], + "width": ["3"], + } + + As: + + .. code-block:: XML + + <color>red</color><height>6.1</height><width>3</width><color>blue</color> + + A tag be repeated multiple times to represent multiple list elements. + """ + +
[docs] def encode(self, obj: Mapping[str, Any]) -> str: + """Encode the object as XML.""" + if not isinstance(obj, dict): + raise TypeError(f"Expected {obj} to be of type dict, got {type(obj)}") + return "".join(_write_tag(key, value) for key, value in obj.items())
+ +
[docs] def decode(self, text: str) -> Dict[str, List[str]]: + """Decode the XML as an object.""" + tag_parser = TagParser() + tag_parser.feed(text) + if not tag_parser.success: + return {} + return dict(tag_parser.parse_data)
+ +
[docs] def get_instruction_segment(self) -> str: + """Format the instructions segment.""" + return ( + "Please enclose the extracted information in HTML style tags with the tag" + " name corresponding to the corresponding component ID. Use angle style" + " brackets for the tags ('>' and '<'). Only output tags when you're" + " confident about the information that was extracted from the user's query." + " If you can extract several pieces of relevant information from the query," + " then include all of them. If the type is an array, please repeat the" + " corresponding tag name multiple times once for each relevant extraction." + " Do NOT output anything except for the extracted information. Only output" + " information inside the HTML style tags. Do not include any notes or any" + " clarifications. " + )
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/examples.html b/_modules/kor/examples.html new file mode 100644 index 0000000..72c03e8 --- /dev/null +++ b/_modules/kor/examples.html @@ -0,0 +1,427 @@ + + + + + + + + kor.examples — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.examples

+"""Module for code that generates examples for a given input.
+
+At the moment, this code only has a simple implementation that concatenates all the
+examples, but one may want to select or generate examples in a smarter way, or take
+into account the finite size of the context window and limit the number of examples.
+
+The code uses a default encoding of XML. This encoding should match the parser.
+"""
+from typing import Any, List, Tuple
+
+from kor.nodes import (
+    AbstractSchemaNode,
+    AbstractVisitor,
+    ExtractionSchemaNode,
+    Object,
+    Option,
+    Selection,
+    TypeVar,
+)
+
+T = TypeVar("T")
+
+
+
[docs]class SimpleExampleAggregator(AbstractVisitor[List[Tuple[str, str]]]): + """Use to visit node and all of its descendants and aggregates all examples.""" + +
[docs] def visit_option(self, node: "Option", **kwargs: Any) -> List[Tuple[str, str]]: + """Should not visit Options directly.""" + raise AssertionError("Should never visit an Option node.")
+ + @staticmethod + def _assemble_output(node: AbstractSchemaNode, data: Any) -> Any: + """Assemble the output data according to the type of the node.""" + if not data: + return {} + if node.many and not isinstance(data, (tuple, list)): + data = [data] + return {node.id: data} + +
[docs] def visit_object(self, node: "Object", **kwargs: Any) -> List[Tuple[str, str]]: + """Implementation of an object visitor.""" + examples = [] + if node.examples: + object_examples = [ + # Looks like false positive from mypy + # Can investigate how to simplify at a later point. + ( + example_input, + self._assemble_output(node, example_output), + ) + for example_input, example_output in node.examples + ] + examples.extend(object_examples) + + # Collect examples from children + for child in node.attributes: + child_examples = child.accept(self) + # Take care of namespaces + child_examples = [ + (example_input, self._assemble_output(node, example_output)) + for example_input, example_output in child_examples + ] + examples.extend(child_examples) + + return examples
+ +
[docs] def visit_selection( + self, node: "Selection", **kwargs: Any + ) -> List[Tuple[str, str]]: + """Selection visitor.""" + examples = [] + for option in node.options: + for example in option.examples: + examples.append((example, self._assemble_output(node, option.id))) + + for example_input, example_output in node.examples: + examples.append( + (example_input, self._assemble_output(node, example_output)) + ) + + for null_example in node.null_examples: + examples.append((null_example, "")) + return examples
+ +
[docs] def visit_default( + self, node: "AbstractSchemaNode", **kwargs: Any + ) -> List[Tuple[str, str]]: + """Default visitor implementation.""" + if not isinstance(node, ExtractionSchemaNode): + raise AssertionError() + examples = [] + + for text, extraction in node.examples: + value = self._assemble_output(node, extraction) + examples.append((text, value)) + return examples
+ +
[docs] def visit(self, node: "AbstractSchemaNode") -> List[Tuple[str, str]]: + """Entry-point.""" + return node.accept(self)
+ + +# PUBLIC API + + +
[docs]def generate_examples(node: AbstractSchemaNode) -> List[Tuple[str, str]]: + """Generate examples for a given element. + + A rudimentary implementation that simply concatenates all available examples + from the components across the entire element tree. + + Does not provide a way to impose constraints (e.g., select a subset of examples + to meet a constraint on the overall number of tokens.) + + Args: + node: AbstractInput + + Returns: + list of 2-tuples containing input, output pairs + """ + return SimpleExampleAggregator().visit(node)
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/exceptions.html b/_modules/kor/exceptions.html new file mode 100644 index 0000000..7d7d4e9 --- /dev/null +++ b/_modules/kor/exceptions.html @@ -0,0 +1,316 @@ + + + + + + + + kor.exceptions — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.exceptions

+
[docs]class KorException(Exception): + """Base class for all Kor exceptions."""
+ + +
[docs]class ParseError(KorException): + """Exception for parsing errors."""
+ + +
[docs]class ValidationError(KorException): + """Exception for validators."""
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/extraction/api.html b/_modules/kor/extraction/api.html new file mode 100644 index 0000000..352fcdd --- /dev/null +++ b/_modules/kor/extraction/api.html @@ -0,0 +1,494 @@ + + + + + + + + kor.extraction.api — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.extraction.api

+"""Kor API for extraction related functionality."""
+import asyncio
+from typing import Any, Callable, List, Optional, Sequence, Type, Union, cast
+
+from langchain.chains import LLMChain
+from langchain.docstore.document import Document
+from langchain.prompts import PromptTemplate
+
+from kor.extraction.parser import KorParser
+
+try:  # Handle breaking change in langchain
+    from langchain.base_language import BaseLanguageModel
+except ImportError:
+    from langchain.schema import BaseLanguageModel  # type: ignore
+
+from kor.encoders import Encoder, InputFormatter, initialize_encoder
+from kor.extraction.typedefs import DocumentExtraction, Extraction
+from kor.nodes import Object
+from kor.prompts import create_langchain_prompt
+from kor.type_descriptors import TypeDescriptor, initialize_type_descriptors
+from kor.validators import Validator
+
+
+async def _extract_from_document_with_semaphore(
+    semaphore: asyncio.Semaphore,
+    chain: LLMChain,
+    document: Document,
+    uid: str,
+    source_uid: str,
+) -> DocumentExtraction:
+    """Extract from document with a semaphore to limit concurrency."""
+    async with semaphore:
+        extraction_result: Extraction = cast(
+            Extraction, await chain.arun(document.page_content)
+        )
+        return {
+            "uid": uid,
+            "source_uid": source_uid,
+            "data": extraction_result["data"],
+            "raw": extraction_result["raw"],
+            "validated_data": extraction_result["validated_data"],
+            "errors": extraction_result["errors"],
+        }
+
+
+# PUBLIC API
+
+
+
[docs]def create_extraction_chain( + llm: BaseLanguageModel, + node: Object, + *, + encoder_or_encoder_class: Union[Type[Encoder], Encoder, str] = "csv", + type_descriptor: Union[TypeDescriptor, str] = "typescript", + validator: Optional[Validator] = None, + input_formatter: InputFormatter = None, + instruction_template: Optional[PromptTemplate] = None, + verbose: Optional[bool] = None, + **encoder_kwargs: Any, +) -> LLMChain: + """Create an extraction chain. + + Args: + llm: the language model used for extraction + node: the schematic description of what to extract from text + encoder_or_encoder_class: Either an encoder instance, an encoder class + or a string representing the encoder class + type_descriptor: either a TypeDescriptor or a string representing the type \ + descriptor name + validator: optional validator to use for validation + input_formatter: the formatter to use for encoding the input. Used for \ + both input examples and the text to be analyzed. + * `None`: use for single sentences or single paragraph, no formatting + * `triple_quotes`: for long text, surround input with \"\"\" + * `text_prefix`: for long text, triple_quote with `TEXT: ` prefix + * `Callable`: user provided function + instruction_template: optional prompt template to use, use to over-ride prompt + used for generating the instruction section of the prompt. + It accepts 2 optional input variables: + * "type_description": type description of the node (from TypeDescriptor) + * "format_instructions": information on how to format the output + (from Encoder) + verbose: if provided, sets the verbosity on the chain, otherwise default + verbosity of the chain will be used + encoder_kwargs: Keyword arguments to pass to the encoder class + + Returns: + A langchain chain + + Examples: + + .. code-block:: python + + # For CSV encoding + chain = create_extraction_chain(llm, node, encoder_or_encoder_class="csv") + + # For JSON encoding + chain = create_extraction_chain(llm, node, encoder_or_encoder_class="JSON", + input_formatter="triple_quotes") + """ + if not isinstance(node, Object): + raise ValueError(f"node must be an Object got {type(node)}") + encoder = initialize_encoder(encoder_or_encoder_class, node, **encoder_kwargs) + type_descriptor_to_use = initialize_type_descriptors(type_descriptor) + + chain_kwargs = {} + if verbose is not None: + chain_kwargs["verbose"] = verbose + + return LLMChain( + llm=llm, + prompt=create_langchain_prompt( + node, + encoder, + type_descriptor_to_use, + validator=validator, + instruction_template=instruction_template, + input_formatter=input_formatter, + ), + output_parser=KorParser(encoder=encoder, validator=validator, schema_=node), + **chain_kwargs, + )
+ + +
[docs]async def extract_from_documents( + chain: LLMChain, + documents: Sequence[Document], + *, + max_concurrency: int = 1, + use_uid: bool = False, + extraction_uid_function: Optional[Callable[[Document], str]] = None, + return_exceptions: bool = False, +) -> List[Union[DocumentExtraction, Exception]]: + """Run extraction through all the given documents. + + Attention: When using this function with a large number of documents, mind the bill + since this can use a lot of tokens! + + Concurrency is currently limited using a semaphore. This is a temporary + and can be changed to a queue implementation to support a non-materialized stream + of documents. + + Args: + chain: the extraction chain to use for extraction + documents: the documents to run extraction on + max_concurrency: the maximum number of concurrent requests to make, + uses a semaphore to limit concurrency + use_uid: If True, will use a uid attribute in metadata if it exists + will raise error if attribute does not exist. + If False, will use the index of the document in the list as the uid + extraction_uid_function: Optional function to use to generate the uid for + a given DocumentExtraction. If not provided, will use the uid + of the document. + return_exceptions: named argument passed to asyncio.gather + + Returns: + A list of extraction results + if return_exceptions = True, the exceptions may be returned as well. + """ + semaphore = asyncio.Semaphore(value=max_concurrency) + + tasks = [] + for idx, doc in enumerate(documents): + if use_uid: + source_uid = doc.metadata.get("uid") + if source_uid is None: + raise ValueError( + f"uid not found in document metadata for document {idx}" + ) + # C + source_uid = str(source_uid) + else: + source_uid = str(idx) + + extraction_uid = ( + extraction_uid_function(doc) if extraction_uid_function else source_uid + ) + + tasks.append( + asyncio.ensure_future( + _extract_from_document_with_semaphore( + semaphore, chain, doc, extraction_uid, source_uid + ) + ) + ) + + results = await asyncio.gather(*tasks, return_exceptions=return_exceptions) + return results
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/extraction/parser.html b/_modules/kor/extraction/parser.html new file mode 100644 index 0000000..344543e --- /dev/null +++ b/_modules/kor/extraction/parser.html @@ -0,0 +1,383 @@ + + + + + + + + kor.extraction.parser — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.extraction.parser

+from __future__ import annotations
+
+from typing import List, Optional
+
+from pydantic import Extra
+
+from kor.encoders import Encoder
+from kor.exceptions import ParseError
+from kor.extraction.typedefs import Extraction
+from kor.nodes import Object
+from kor.validators import Validator
+
+try:
+    from langchain.output_parsers.base import BaseOutputParser
+except ImportError:
+    from langchain.schema import BaseOutputParser  # type: ignore
+
+
+
[docs]class KorParser(BaseOutputParser): + """A Kor langchain parser integration. + + This parser can use any of Kor's encoders to support encoding/decoding + different data formats. + """ + + encoder: Encoder + schema_: Object + validator: Optional[Validator] = None + + @property + def _type(self) -> str: + """Declare the type property.""" + return "KorEncoder" + +
[docs] def parse(self, text: str) -> Extraction: + """Parse the text.""" + try: + data = self.encoder.decode(text) + except ParseError as e: + return {"data": {}, "raw": text, "errors": [e], "validated_data": {}} + + key_id = self.schema_.id + + errors: List[Exception] + + if key_id not in data: + if data: # We got something parsed, but it doesn't match the schema. + errors = [ + ParseError( + "The LLM has returned structured data which does not match the" + " expected schema. Providing additional examples may help" + " improve the parse." + ) + ] + else: + errors = [] + return {"data": {}, "raw": text, "errors": errors, "validated_data": {}} + + obj_data = data[key_id] + + if self.validator: + validated_data, errors = self.validator.clean_data(obj_data) + else: + validated_data, errors = {}, [] + + return { + "data": data, + "raw": text, + "errors": errors, + "validated_data": validated_data, + }
+ +
[docs] class Config: + """Configuration for this pydantic object.""" + + extra = Extra.forbid + arbitrary_types_allowed = True
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/extraction/typedefs.html b/_modules/kor/extraction/typedefs.html new file mode 100644 index 0000000..dd59a8b --- /dev/null +++ b/_modules/kor/extraction/typedefs.html @@ -0,0 +1,337 @@ + + + + + + + + kor.extraction.typedefs — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.extraction.typedefs

+"""Type definitions for the extraction package."""
+from typing import Any, Dict, List, TypedDict
+
+
+
[docs]class Extraction(TypedDict): + """Type-definition for an extraction result.""" + + raw: str + """The raw output from the LLM.""" + data: Dict[str, Any] + """The decoding of the raw output from the LLM without any further processing.""" + validated_data: Dict[str, Any] + """The validated data if a validator was provided.""" + errors: List[Exception] + """Any errors encountered during decoding or validation."""
+ + +
[docs]class DocumentExtraction(Extraction): + """Type-definition for a document extraction result. + + The original extraction typedefs together with the unique identifiers for the result + itself as well as the source document. + + Identifiers are included to make it easier to link the extraction result + to the source content. + """ + + uid: str + """The uid of the extraction result.""" + source_uid: str + """The source uid of the document from which data was extracted."""
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/nodes.html b/_modules/kor/nodes.html new file mode 100644 index 0000000..653c5b5 --- /dev/null +++ b/_modules/kor/nodes.html @@ -0,0 +1,598 @@ + + + + + + + + kor.nodes — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.nodes

+"""Definitions of input elements."""
+from __future__ import annotations
+
+import abc
+import copy
+from typing import (
+    Any,
+    Generic,
+    Mapping,
+    Optional,
+    Sequence,
+    Tuple,
+    Type,
+    TypeVar,
+    Union,
+)
+
+from pydantic import BaseModel
+
+from ._pydantic import PYDANTIC_MAJOR_VERSION
+
+# Name of field to store the type discriminator
+TYPE_DISCRIMINATOR_FIELD = "$type"
+
+T = TypeVar("T")
+
+
+# Visitor is defined here for now, to avoid circular imports.
+
[docs]class AbstractVisitor(Generic[T], abc.ABC): + """An abstract visitor.""" + +
[docs] def visit_text(self, node: Text, **kwargs: Any) -> T: + """Visit text node.""" + return self.visit_default(node, **kwargs)
+ +
[docs] def visit_number(self, node: Number, **kwargs: Any) -> T: + """Visit text node.""" + return self.visit_default(node, **kwargs)
+ +
[docs] def visit_object(self, node: Object, **kwargs: Any) -> T: + """Visit object node.""" + return self.visit_default(node, **kwargs)
+ +
[docs] def visit_selection(self, node: Selection, **kwargs: Any) -> T: + """Visit selection node.""" + return self.visit_default(node, **kwargs)
+ +
[docs] def visit_option(self, node: Option, **kwargs: Any) -> T: + """Visit option node.""" + return self.visit_default(node, **kwargs)
+ +
[docs] def visit_default(self, node: AbstractSchemaNode, **kwargs: Any) -> T: + """Default node implementation.""" + raise NotImplementedError()
+ +
[docs] def visit_bool(self, node: Bool, **kwargs: Any) -> T: + """Visit bool node.""" + return self.visit_default(node, **kwargs)
+ + +
[docs]class AbstractSchemaNode(BaseModel): + """Abstract schema node. + + Each node is expected to have a unique ID, and should + only use alphanumeric characters. + + The ID should be unique across all inputs that belong + to a given form. + + The description should describe what the node represents. + It is used during prompt generation. + """ + + id: str + description: str = "" + many: bool = False + +
[docs] @abc.abstractmethod + def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + raise NotImplementedError()
+ + # Update return type to `Self` when bumping python version. +
[docs] def replace( + self, + id: Optional[str] = None, # pylint: disable=redefined-builtin + description: Optional[str] = None, + ) -> "AbstractSchemaNode": + """Wrapper around data-classes replace.""" + new_object = copy.copy(self) + if id: + new_object.id = id + if description: + new_object.description = description + return new_object
+ + +
[docs]class ExtractionSchemaNode(AbstractSchemaNode, abc.ABC): + """An abstract definition for inputs that involve extraction. + + An extraction input can be associated with extraction examples. + + An extraction example is a 2-tuple composed of a text segment and the expected + extraction. + + For example: + + .. code-block:: python + + [ + ("I bought this cookie for $10", "$10"), + ("Eggs cost twelve dollars", "twelve dollars"), + ] + """ + + examples: Sequence[ + Tuple[str, Union[bool, int, float, str, Sequence[Union[str, int, float, bool]]]] + ] = tuple() + + def __init__(self, **kwargs: Any) -> None: + """Initialize.""" + super().__init__(**kwargs) + if PYDANTIC_MAJOR_VERSION == 1: + self.__dict__[TYPE_DISCRIMINATOR_FIELD] = type(self).__name__ + +
[docs] @classmethod + def parse_obj(cls, data: dict) -> ExtractionSchemaNode: + """Parse an object.""" + if PYDANTIC_MAJOR_VERSION != 1: + raise NotImplementedError("Only supported for pydantic 1.x") + type_ = data.pop(TYPE_DISCRIMINATOR_FIELD, None) + if type_ is None: + raise ValueError(f"Need to specify type ({TYPE_DISCRIMINATOR_FIELD})") + for sub in cls.__subclasses__(): + if type_ == sub.__name__: + return sub(**data) + raise TypeError(f"Unknown sub-type: {type_}")
+ +
[docs] @classmethod + def validate(cls: Type[ExtractionSchemaNode], v: Any) -> ExtractionSchemaNode: + if isinstance(v, dict): + return cls.parse_obj(v) + elif isinstance(v, cls): + return v + else: + raise TypeError(f"Unsupported type: {type(v)}")
+ + +
[docs]class Number(ExtractionSchemaNode): + """Built-in number input.""" + + examples: Sequence[ + Tuple[str, Union[int, float, Sequence[Union[float, int]]]] + ] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_number(self, **kwargs)
+ + +
[docs]class Text(ExtractionSchemaNode): + """Built-in text input.""" + + examples: Sequence[Tuple[str, Union[Sequence[str], str]]] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_text(self, **kwargs)
+ + +
[docs]class Bool(ExtractionSchemaNode): + """Built-in bool input.""" + + examples: Sequence[Tuple[str, Union[Sequence[bool], bool]]] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_bool(self, **kwargs)
+ + +
[docs]class Option(AbstractSchemaNode): + """Built-in option input must be part of a selection input.""" + + examples: Sequence[str] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_option(self, **kwargs)
+ + +
[docs]class Selection(AbstractSchemaNode): + """Built-in selection node (aka Enum). + + A selection input is composed of one or more options. + + A selectio node supports both examples and null_examples. + + Null examples are segments of text for which nothing should be extracted. + + Examples: + + .. code-block:: python + + selection = Selection( + id="species", + description="What is your favorite animal species?", + options=[ + Option(id="dog", description="Dog"), + Option(id="cat", description="Cat"), + Option(id="bird", description="Bird"), + ], + examples=[ + ("I like dogs", "dog"), + ("I like cats", "cat"), + ("I like birds", "bird"), + ], + null_examples=[ + "I like flowers", + ], + many=False + ) + """ + + options: Sequence[Option] + examples: Sequence[Tuple[str, Union[str, Sequence[str]]]] = tuple() + null_examples: Sequence[str] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_selection(self, **kwargs)
+ + +
[docs]class Object(AbstractSchemaNode): + """Built-in representation for an object. + + Use an object node to represent an entire object that should be extracted. + + An extraction input can be associated with 2 different types of examples: + + Example: + + .. code-block:: python + + object = Object( + id="cookie", + description="Information about a cookie including price and name.", + attributes=[ + Text(id="name", description="The name of the cookie"), + Number(id="price", description="The price of the cookie"), + ], + examples=[ + ("I bought this Big Cookie for $10", + {"name": "Big Cookie", "price": "$10"}), + ("Eggs cost twelve dollars", {}), # Not a cookie + ], + ) + + """ + + attributes: Sequence[Union[ExtractionSchemaNode, Selection, Object]] + + examples: Sequence[ + Tuple[ + str, + Union[ + Sequence[Mapping[str, Any]], + Mapping[str, Any], + ], + ] + ] = tuple() + +
[docs] def accept(self, visitor: AbstractVisitor[T], **kwargs: Any) -> T: + """Accept a visitor.""" + return visitor.visit_object(self, **kwargs)
+ +
[docs] @classmethod + def parse_raw(cls, *args: Any, **kwargs: Any) -> Object: + """Parse raw data.""" + if PYDANTIC_MAJOR_VERSION != 1: + raise NotImplementedError( + f"parse_raw is not supported for pydantic {PYDANTIC_MAJOR_VERSION}" + ) + return super().parse_raw(*args, **kwargs)
+ +
[docs] @classmethod + def parse_obj(cls, *args: Any, **kwargs: Any) -> Object: + """Parse an object.""" + if PYDANTIC_MAJOR_VERSION != 1: + raise NotImplementedError( + f"parse_obj is not supported for pydantic {PYDANTIC_MAJOR_VERSION}" + ) + return super().parse_obj(*args, **kwargs)
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/prompts.html b/_modules/kor/prompts.html new file mode 100644 index 0000000..36163b5 --- /dev/null +++ b/_modules/kor/prompts.html @@ -0,0 +1,485 @@ + + + + + + + + kor.prompts — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.prompts

+"""Code to dynamically generate appropriate LLM prompts."""
+from __future__ import annotations
+
+from typing import Any, List, Optional, Tuple
+
+from langchain.prompts import BasePromptTemplate, PromptTemplate
+from langchain.schema import (
+    AIMessage,
+    BaseMessage,
+    HumanMessage,
+    PromptValue,
+    SystemMessage,
+)
+
+from kor.encoders import Encoder
+from kor.encoders.encode import InputFormatter, encode_examples, format_text
+from kor.examples import generate_examples
+from kor.extraction.parser import KorParser
+from kor.nodes import Object
+from kor.type_descriptors import TypeDescriptor
+
+try:
+    # Use pydantic v1 namespace since working with langchain
+    from pydantic.v1 import Extra  # type: ignore[assignment]
+except ImportError:
+    from pydantic import Extra  # type: ignore[assignment]
+
+from .validators import Validator
+
+DEFAULT_INSTRUCTION_TEMPLATE = PromptTemplate(
+    input_variables=["type_description", "format_instructions"],
+    template=(
+        "Your goal is to extract structured information from the user's input that"
+        " matches the form described below. When extracting information please make"
+        " sure it matches the type information exactly. Do not add any attributes that"
+        " do not appear in the schema shown below.\n\n"
+        "{type_description}\n\n"
+        "{format_instructions}\n\n"
+    ),
+)
+
+
+
[docs]class ExtractionPromptValue(PromptValue): + """Integration with langchain prompt format.""" + + string: str + messages: List[BaseMessage] + +
[docs] class Config: + """Configuration for this pydantic object.""" + + extra = Extra.forbid + arbitrary_types_allowed = True
+ +
[docs] def to_string(self) -> str: + """Format the prompt to a string.""" + return self.string
+ +
[docs] def to_messages(self) -> List[BaseMessage]: + """Get materialized messages.""" + return self.messages
+ + +
[docs]class ExtractionPromptTemplate(BasePromptTemplate): + """Extraction prompt template.""" + + encoder: Encoder + node: Object + type_descriptor: TypeDescriptor + input_formatter: InputFormatter + instruction_template: PromptTemplate + +
[docs] class Config: + """Configuration for this pydantic object.""" + + extra = Extra.forbid + arbitrary_types_allowed = True
+ +
[docs] def format_prompt( # type: ignore[override] + self, + text: str, + ) -> PromptValue: + """Format the prompt.""" + text = format_text(text, input_formatter=self.input_formatter) + return ExtractionPromptValue( + string=self.to_string(text), messages=self.to_messages(text) + )
+ +
[docs] def format(self, **kwargs: Any) -> str: + """Implementation of deprecated format method.""" + raise NotImplementedError()
+ + @property + def _prompt_type(self) -> str: + """Prompt type.""" + return "ExtractionPromptTemplate" + +
[docs] def to_string(self, text: str) -> str: + """Format the template to a string.""" + instruction_segment = self.format_instruction_segment(self.node) + encoded_examples = self.generate_encoded_examples(self.node) + formatted_examples: List[str] = [] + + for in_example, output in encoded_examples: + formatted_examples.extend( + [ + f"Input: {in_example}", + f"Output: {output}", + ] + ) + + formatted_examples.append(f"Input: {text}\nOutput:") + input_output_block = "\n".join(formatted_examples) + return f"{instruction_segment}\n\n{input_output_block}"
+ +
[docs] def to_messages(self, text: str) -> List[BaseMessage]: + """Format the template to chat messages.""" + instruction_segment = self.format_instruction_segment(self.node) + + messages: List[BaseMessage] = [SystemMessage(content=instruction_segment)] + encoded_examples = self.generate_encoded_examples(self.node) + + for example_input, example_output in encoded_examples: + messages.extend( + [ + HumanMessage(content=example_input), + AIMessage(content=example_output), + ] + ) + + messages.append(HumanMessage(content=text)) + return messages
+ +
[docs] def generate_encoded_examples(self, node: Object) -> List[Tuple[str, str]]: + """Generate encoded examples.""" + examples = generate_examples(node) + return encode_examples( + examples, self.encoder, input_formatter=self.input_formatter + )
+ +
[docs] def format_instruction_segment(self, node: Object) -> str: + """Generate the instruction segment of the extraction.""" + type_description = self.type_descriptor.describe(node) + format_instructions = self.encoder.get_instruction_segment() + input_variables = self.instruction_template.input_variables + + formatting_kwargs = {} + + if "type_description" in input_variables: + formatting_kwargs["type_description"] = type_description + + if "format_instructions" in input_variables: + formatting_kwargs["format_instructions"] = format_instructions + + return self.instruction_template.format(**formatting_kwargs)
+ + +# PUBLIC API + + +
[docs]def create_langchain_prompt( + schema: Object, + encoder: Encoder, + type_descriptor: TypeDescriptor, + *, + validator: Optional[Validator] = None, + input_formatter: InputFormatter = None, + instruction_template: Optional[PromptTemplate] = None, +) -> ExtractionPromptTemplate: + """Create a langchain style prompt with specified encoder.""" + return ExtractionPromptTemplate( + input_variables=["text"], + output_parser=KorParser(encoder=encoder, validator=validator, schema_=schema), + encoder=encoder, + node=schema, + input_formatter=input_formatter, + type_descriptor=type_descriptor, + instruction_template=instruction_template or DEFAULT_INSTRUCTION_TEMPLATE, + )
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/type_descriptors.html b/_modules/kor/type_descriptors.html new file mode 100644 index 0000000..5e33935 --- /dev/null +++ b/_modules/kor/type_descriptors.html @@ -0,0 +1,443 @@ + + + + + + + + kor.type_descriptors — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.type_descriptors

+"""Code that takes an Object schema and outputs a string that describes its schema.
+
+Without fine-tuning the LLM, the quality of the response may end up depending
+on details such as the schema description in the prompt.
+
+Users can implement their own type descriptors or customize an existing one
+using inheritance and over-loading and provide the type-descriptors to
+the create_extraction_chain function.
+"""
+import abc
+from typing import Any, Iterable, List, TypeVar, Union
+
+from kor.nodes import (
+    AbstractSchemaNode,
+    AbstractVisitor,
+    Bool,
+    Number,
+    Object,
+    Selection,
+    Text,
+)
+
+T = TypeVar("T")
+
+# PUBLIC API
+
+
+
[docs]class TypeDescriptor(AbstractVisitor[T], abc.ABC): + """Abstract interface for a type-descriptor. + + A type-descriptor is responsible for taking in a schema and outputting its type + as a string. The description is used to help the LLM generate structured output. + + A type-descriptor is a visitor that can be used to traverse the schema recursively. + """ + +
[docs] @abc.abstractmethod + def describe(self, node: Object) -> str: + """Take in node and describe its type as a string.""" + raise NotImplementedError()
+ + +
[docs]class BulletPointDescriptor(TypeDescriptor[Iterable[str]]): + """Generate a bullet point style schema description.""" + +
[docs] def visit_default(self, node: "AbstractSchemaNode", **kwargs: Any) -> List[str]: + """Default action for a node.""" + depth = kwargs["depth"] + space = "* " + depth * " " + return [f"{space}{node.id}: {node.__class__.__name__} # {node.description}"]
+ +
[docs] def visit_object(self, node: Object, **kwargs: Any) -> List[str]: + """Visit an object node.""" + depth = kwargs["depth"] + code_lines = self.visit_default(node, depth=depth) + for child in node.attributes: + code_lines.extend(child.accept(self, depth=depth + 1)) + return code_lines
+ +
[docs] def describe(self, node: Object) -> str: + """Describe the type of the given node.""" + code_lines = node.accept(self, depth=0) + return "\n".join(code_lines)
+ + +
[docs]class TypeScriptDescriptor(TypeDescriptor[Iterable[str]]): + """Generate a typescript style schema description.""" + +
[docs] def visit_default(self, node: "AbstractSchemaNode", **kwargs: Any) -> List[str]: + """Default action for a node.""" + depth = kwargs["depth"] + space = depth * " " + + if isinstance(node, Selection): + finalized_type = " | ".join('"' + s.id + '"' for s in node.options) + elif isinstance(node, Text): + finalized_type = "string" + elif isinstance(node, Number): + finalized_type = "number" + elif isinstance(node, Bool): + finalized_type = "boolean" + else: + raise NotImplementedError() + + if node.many: + finalized_type = "Array<" + finalized_type + ">" + + return [f"{space}{node.id}: {finalized_type} // {node.description}"]
+ +
[docs] def visit_object(self, node: Object, **kwargs: Any) -> List[str]: + """Visit an object node.""" + depth = kwargs["depth"] + space = depth * " " + + if node.many: + many_formatter = "Array<" + else: + many_formatter = "" + + code_lines = [f"{space}{node.id}: {many_formatter}{{ // {node.description}"] + + for child in node.attributes: + code_lines.extend(child.accept(self, depth=depth + 1)) + + if node.many: + many_formatter = ">" + else: + many_formatter = "" + + code_lines.append(f"{space}}}{many_formatter}") + return code_lines
+ +
[docs] def describe(self, node: "Object") -> str: + """Describe the node type in TypeScript notation.""" + if not isinstance(node, Object): + raise TypeError(f"Expecting an Object node got {node}") + + code_lines = node.accept(self, depth=0) + code = "\n".join(code_lines) + return f"```TypeScript\n\n{code}\n```\n"
+ + +
[docs]def initialize_type_descriptors( + type_descriptor: Union[TypeDescriptor, str] +) -> TypeDescriptor: + """Initialize the type descriptors.""" + if isinstance(type_descriptor, str): + if type_descriptor == "bullet_point": + return BulletPointDescriptor() + elif type_descriptor == "typescript": + return TypeScriptDescriptor() + else: + raise ValueError( + f"Unknown type descriptor: {type_descriptor}. Use one of: bullet_point," + " typescript or else provide an instance of TypeDescriptor." + ) + return type_descriptor
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/kor/validators.html b/_modules/kor/validators.html new file mode 100644 index 0000000..a5b5a85 --- /dev/null +++ b/_modules/kor/validators.html @@ -0,0 +1,384 @@ + + + + + + + + kor.validators — 😼 Kor 1.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+

+ +
+
+ +
+
+
+
+ +
+ +

Source code for kor.validators

+"""Define validator interface and provide built-in validators for common-use cases."""
+import abc
+from typing import Any, List, Mapping, Optional, Tuple, Type, Union
+
+from pydantic import BaseModel, ValidationError
+
+from ._pydantic import PYDANTIC_MAJOR_VERSION
+
+
+
[docs]class Validator(abc.ABC): +
[docs] @abc.abstractmethod + def clean_data( + self, data: Union[List[Mapping[str, Any]], Mapping[str, Any]] + ) -> Tuple[Any, List[Exception]]: + """Validate the data and return a cleaned version of it. + + Args: + data: the parsed data + + Returns: + a cleaned version of the data, the type depends on the validator + """ + raise NotImplementedError()
+ + +
[docs]class PydanticValidator(Validator): + """Use a pydantic model for validation.""" + + def __init__(self, model_class: Type[BaseModel], many: bool) -> None: + """Create a validator for a pydantic model. + + Args: + model_class: The pydantic model class to use for validation + many: Whether the data is expected to correspond to a single moder + or a list of models + """ + self.model_class = model_class + self.many = many + +
[docs] def clean_data( + self, data: Any + ) -> Tuple[Union[Optional[BaseModel], List[BaseModel]], List[Exception]]: + """Clean the data using the pydantic model. + + Args: + data: the parsed data + + Returns: + cleaned data instantiated as the corresponding pydantic model + """ + model_ = self.model_class # a proxy to make code fit in char limit + + if self.many: + exceptions: List[Exception] = [] + records: List[BaseModel] = [] + + for item in data: + try: + if PYDANTIC_MAJOR_VERSION == 1: + record = model_.parse_obj(item) # type: ignore[attr-defined] + else: + record = model_.model_validate( # type: ignore[attr-defined] + item + ) + + records.append(record) + except ValidationError as e: + exceptions.append(e) + return records, exceptions + else: + try: + if PYDANTIC_MAJOR_VERSION == 1: + record = model_.parse_obj(data) # type: ignore[attr-defined] + else: + record = model_.model_validate(data) # type: ignore[attr-defined] + return record, [] + except ValidationError as e: + return None, [e]
+
+ +
+ +
+
+ + +
+
+
+
+
+ + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/_panels_static/panels-bootstrap.5fd3999ee7762ccc51105388f4a9d115.css b/_panels_static/panels-bootstrap.5fd3999ee7762ccc51105388f4a9d115.css new file mode 100644 index 0000000..1b057df --- /dev/null +++ b/_panels_static/panels-bootstrap.5fd3999ee7762ccc51105388f4a9d115.css @@ -0,0 +1 @@ +.badge{border-radius:.25rem;display:inline-block;font-size:75%;font-weight:700;line-height:1;padding:.25em .4em;text-align:center;vertical-align:baseline;white-space:nowrap}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#007bff;color:#fff}.badge-primary[href]:focus,.badge-primary[href]:hover{background-color:#0062cc;color:#fff;text-decoration:none}.badge-secondary{background-color:#6c757d;color:#fff}.badge-secondary[href]:focus,.badge-secondary[href]:hover{background-color:#545b62;color:#fff;text-decoration:none}.badge-success{background-color:#28a745;color:#fff}.badge-success[href]:focus,.badge-success[href]:hover{background-color:#1e7e34;color:#fff;text-decoration:none}.badge-info{background-color:#17a2b8;color:#fff}.badge-info[href]:focus,.badge-info[href]:hover{background-color:#117a8b;color:#fff;text-decoration:none}.badge-warning{background-color:#ffc107;color:#212529}.badge-warning[href]:focus,.badge-warning[href]:hover{background-color:#d39e00;color:#212529;text-decoration:none}.badge-danger{background-color:#dc3545;color:#fff}.badge-danger[href]:focus,.badge-danger[href]:hover{background-color:#bd2130;color:#fff;text-decoration:none}.badge-light{background-color:#f8f9fa;color:#212529}.badge-light[href]:focus,.badge-light[href]:hover{background-color:#dae0e5;color:#212529;text-decoration:none}.badge-dark{background-color:#343a40;color:#fff}.badge-dark[href]:focus,.badge-dark[href]:hover{background-color:#1d2124;color:#fff;text-decoration:none}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#212529;cursor:pointer;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;vertical-align:middle}.btn:hover{color:#212529;text-decoration:none}.btn:visited{color:#212529}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,0.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}@media (prefers-reduced-motion: reduce){.btn{transition:none}}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#007bff;border-color:#007bff;color:#fff}.btn-primary:visited{color:#fff}.btn-primary:hover{background-color:#0069d9;border-color:#0062cc;color:#fff}.btn-primary.focus,.btn-primary:focus{background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(0,123,255,0.5);color:#fff}.btn-primary.disabled,.btn-primary:disabled{background-color:#007bff;border-color:#007bff;color:#fff}.btn-primary.active:not(:disabled):not(.disabled),.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#0062cc;border-color:#005cbf;color:#fff}.btn-primary.active:not(:disabled):not(.disabled):focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,0.5)}.btn-secondary{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-secondary:visited{color:#fff}.btn-secondary:hover{background-color:#5a6268;border-color:#545b62;color:#fff}.btn-secondary.focus,.btn-secondary:focus{background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(108,117,125,0.5);color:#fff}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-secondary.active:not(:disabled):not(.disabled),.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#545b62;border-color:#4e555b;color:#fff}.btn-secondary.active:not(:disabled):not(.disabled):focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-success{background-color:#28a745;border-color:#28a745;color:#fff}.btn-success:visited{color:#fff}.btn-success:hover{background-color:#218838;border-color:#1e7e34;color:#fff}.btn-success.focus,.btn-success:focus{background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(40,167,69,0.5);color:#fff}.btn-success.disabled,.btn-success:disabled{background-color:#28a745;border-color:#28a745;color:#fff}.btn-success.active:not(:disabled):not(.disabled),.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#1e7e34;border-color:#1c7430;color:#fff}.btn-success.active:not(:disabled):not(.disabled):focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-info{background-color:#17a2b8;border-color:#17a2b8;color:#fff}.btn-info:visited{color:#fff}.btn-info:hover{background-color:#138496;border-color:#117a8b;color:#fff}.btn-info.focus,.btn-info:focus{background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(23,162,184,0.5);color:#fff}.btn-info.disabled,.btn-info:disabled{background-color:#17a2b8;border-color:#17a2b8;color:#fff}.btn-info.active:not(:disabled):not(.disabled),.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#117a8b;border-color:#10707f;color:#fff}.btn-info.active:not(:disabled):not(.disabled):focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-warning{background-color:#ffc107;border-color:#ffc107;color:#212529}.btn-warning:visited{color:#212529}.btn-warning:hover{background-color:#e0a800;border-color:#d39e00;color:#212529}.btn-warning.focus,.btn-warning:focus{background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(255,193,7,0.5);color:#212529}.btn-warning.disabled,.btn-warning:disabled{background-color:#ffc107;border-color:#ffc107;color:#212529}.btn-warning.active:not(:disabled):not(.disabled),.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#d39e00;border-color:#c69500;color:#212529}.btn-warning.active:not(:disabled):not(.disabled):focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-danger{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-danger:visited{color:#fff}.btn-danger:hover{background-color:#c82333;border-color:#bd2130;color:#fff}.btn-danger.focus,.btn-danger:focus{background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(220,53,69,0.5);color:#fff}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-danger.active:not(:disabled):not(.disabled),.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#bd2130;border-color:#b21f2d;color:#fff}.btn-danger.active:not(:disabled):not(.disabled):focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-light{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light:visited{color:#212529}.btn-light:hover{background-color:#e2e6ea;border-color:#dae0e5;color:#212529}.btn-light.focus,.btn-light:focus{background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(248,249,250,0.5);color:#212529}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light.active:not(:disabled):not(.disabled),.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#dae0e5;border-color:#d3d9df;color:#212529}.btn-light.active:not(:disabled):not(.disabled):focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-dark{background-color:#343a40;border-color:#343a40;color:#fff}.btn-dark:visited{color:#fff}.btn-dark:hover{background-color:#23272b;border-color:#1d2124;color:#fff}.btn-dark.focus,.btn-dark:focus{background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(52,58,64,0.5);color:#fff}.btn-dark.disabled,.btn-dark:disabled{background-color:#343a40;border-color:#343a40;color:#fff}.btn-dark.active:not(:disabled):not(.disabled),.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#1d2124;border-color:#171a1d;color:#fff}.btn-dark.active:not(:disabled):not(.disabled):focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-outline-primary{border-color:#007bff;color:#007bff}.btn-outline-primary:visited{color:#007bff}.btn-outline-primary:hover{background-color:#007bff;border-color:#007bff;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#007bff}.btn-outline-primary.active:not(:disabled):not(.disabled),.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#007bff;border-color:#007bff;color:#fff}.btn-outline-primary.active:not(:disabled):not(.disabled):focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,0.5)}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-outline-secondary:visited{color:#6c757d}.btn-outline-secondary:hover{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#6c757d}.btn-outline-secondary.active:not(:disabled):not(.disabled),.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#6c757d;border-color:#6c757d;color:#fff}.btn-outline-secondary.active:not(:disabled):not(.disabled):focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-success{border-color:#28a745;color:#28a745}.btn-outline-success:visited{color:#28a745}.btn-outline-success:hover{background-color:#28a745;border-color:#28a745;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#28a745}.btn-outline-success.active:not(:disabled):not(.disabled),.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#28a745;border-color:#28a745;color:#fff}.btn-outline-success.active:not(:disabled):not(.disabled):focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-info{border-color:#17a2b8;color:#17a2b8}.btn-outline-info:visited{color:#17a2b8}.btn-outline-info:hover{background-color:#17a2b8;border-color:#17a2b8;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#17a2b8}.btn-outline-info.active:not(:disabled):not(.disabled),.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#17a2b8;border-color:#17a2b8;color:#fff}.btn-outline-info.active:not(:disabled):not(.disabled):focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-warning{border-color:#ffc107;color:#ffc107}.btn-outline-warning:visited{color:#ffc107}.btn-outline-warning:hover{background-color:#ffc107;border-color:#ffc107;color:#212529}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#ffc107}.btn-outline-warning.active:not(:disabled):not(.disabled),.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#ffc107;border-color:#ffc107;color:#212529}.btn-outline-warning.active:not(:disabled):not(.disabled):focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-danger{border-color:#dc3545;color:#dc3545}.btn-outline-danger:visited{color:#dc3545}.btn-outline-danger:hover{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc3545}.btn-outline-danger.active:not(:disabled):not(.disabled),.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#dc3545;border-color:#dc3545;color:#fff}.btn-outline-danger.active:not(:disabled):not(.disabled):focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-light{border-color:#f8f9fa;color:#f8f9fa}.btn-outline-light:visited{color:#f8f9fa}.btn-outline-light:hover{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f8f9fa}.btn-outline-light.active:not(:disabled):not(.disabled),.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light.active:not(:disabled):not(.disabled):focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-dark{border-color:#343a40;color:#343a40}.btn-outline-dark:visited{color:#343a40}.btn-outline-dark:hover{background-color:#343a40;border-color:#343a40;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#343a40}.btn-outline-dark.active:not(:disabled):not(.disabled),.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#343a40;border-color:#343a40;color:#fff}.btn-outline-dark.active:not(:disabled):not(.disabled):focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-link{color:#007bff;font-weight:400;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{box-shadow:none;text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:.3rem;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input.btn-block[type=button],input.btn-block[type=reset],input.btn-block[type=submit]{width:100%}.stretched-link::after{background-color:rgba(0,0,0,0);bottom:0;content:'';left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-wrap{white-space:normal !important}.card{background-clip:border-box;background-color:#fff;border:1px solid rgba(0,0,0,0.125);border-radius:.25rem;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.card>hr{margin-left:0;margin-right:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-bottom:0;margin-top:-.375rem}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:rgba(0,0,0,0.03);border-bottom:1px solid rgba(0,0,0,0.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{background-color:rgba(0,0,0,0.03);border-top:1px solid rgba(0,0,0,0.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem;margin-left:-.625rem;margin-right:-.625rem}.card-header-pills{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.w-100{width:100% !important}.shadow{box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.bg-primary{background-color:#007bff !important}button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc !important}a.bg-primary:focus,a.bg-primary:hover{background-color:#0062cc !important}a.text-primary:focus,a.text-primary:hover{color:#121416 !important}.bg-secondary{background-color:#6c757d !important}button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62 !important}a.bg-secondary:focus,a.bg-secondary:hover{background-color:#545b62 !important}a.text-secondary:focus,a.text-secondary:hover{color:#121416 !important}.bg-success{background-color:#28a745 !important}button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34 !important}a.bg-success:focus,a.bg-success:hover{background-color:#1e7e34 !important}a.text-success:focus,a.text-success:hover{color:#121416 !important}.bg-info{background-color:#17a2b8 !important}button.bg-info:focus,button.bg-info:hover{background-color:#117a8b !important}a.bg-info:focus,a.bg-info:hover{background-color:#117a8b !important}a.text-info:focus,a.text-info:hover{color:#121416 !important}.bg-warning{background-color:#ffc107 !important}button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00 !important}a.bg-warning:focus,a.bg-warning:hover{background-color:#d39e00 !important}a.text-warning:focus,a.text-warning:hover{color:#121416 !important}.bg-danger{background-color:#dc3545 !important}button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130 !important}a.bg-danger:focus,a.bg-danger:hover{background-color:#bd2130 !important}a.text-danger:focus,a.text-danger:hover{color:#121416 !important}.bg-light{background-color:#f8f9fa !important}button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5 !important}a.bg-light:focus,a.bg-light:hover{background-color:#dae0e5 !important}a.text-light:focus,a.text-light:hover{color:#121416 !important}.bg-dark{background-color:#343a40 !important}button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124 !important}a.bg-dark:focus,a.bg-dark:hover{background-color:#1d2124 !important}a.text-dark:focus,a.text-dark:hover{color:#121416 !important}.bg-white{background-color:#fff !important}button.bg-white:focus,button.bg-white:hover{background-color:#e6e6e6 !important}a.bg-white:focus,a.bg-white:hover{background-color:#e6e6e6 !important}a.text-white:focus,a.text-white:hover{color:#121416 !important}.text-primary{color:#007bff !important}.text-secondary{color:#6c757d !important}.text-success{color:#28a745 !important}.text-info{color:#17a2b8 !important}.text-warning{color:#ffc107 !important}.text-danger{color:#dc3545 !important}.text-light{color:#f8f9fa !important}.text-dark{color:#343a40 !important}.text-white{color:#fff !important}.text-body{color:#212529 !important}.text-muted{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.bg-transparent{background-color:transparent !important}.text-justify{text-align:justify !important}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-weight-bolder{font-weight:bolder !important}.font-italic{font-style:italic !important}.container{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width: 576px){.container,.container-sm{max-width:540px}}@media (min-width: 768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width: 992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width: 1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}@media (min-width: 576px){.col-sm{flex-basis:0;flex-grow:1;-ms-flex-positive:1;-ms-flex-preferred-size:0;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media (min-width: 768px){.col-md{flex-basis:0;flex-grow:1;-ms-flex-positive:1;-ms-flex-preferred-size:0;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;max-width:100%;width:auto}.col-md-1{-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media (min-width: 992px){.col-lg{flex-basis:0;flex-grow:1;-ms-flex-positive:1;-ms-flex-preferred-size:0;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media (min-width: 1200px){.col-xl{flex-basis:0;flex-grow:1;-ms-flex-positive:1;-ms-flex-preferred-size:0;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.d-flex{display:-ms-flexbox !important;display:flex !important}.sphinx-bs,.sphinx-bs *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sphinx-bs p{margin-top:0} diff --git a/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css b/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css new file mode 100644 index 0000000..fc14abc --- /dev/null +++ b/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css @@ -0,0 +1 @@ +details.dropdown .summary-title{padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.dropdown:hover{cursor:pointer}details.dropdown .summary-content{cursor:default}details.dropdown summary{list-style:none;padding:1em}details.dropdown summary .octicon.no-title{vertical-align:middle}details.dropdown[open] summary .octicon.no-title{visibility:hidden}details.dropdown summary::-webkit-details-marker{display:none}details.dropdown summary:focus{outline:none}details.dropdown summary:hover .summary-up svg,details.dropdown summary:hover .summary-down svg{opacity:1}details.dropdown .summary-up svg,details.dropdown .summary-down svg{display:block;opacity:.6}details.dropdown .summary-up,details.dropdown .summary-down{pointer-events:none;position:absolute;right:1em;top:.75em}details.dropdown[open] .summary-down{visibility:hidden}details.dropdown:not([open]) .summary-up{visibility:hidden}details.dropdown.fade-in[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out;animation:panels-fade-in .5s ease-in-out}details.dropdown.fade-in-slide-down[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out}@keyframes panels-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes panels-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.octicon{display:inline-block;fill:currentColor;vertical-align:text-top}.tabbed-content{box-shadow:0 -.0625rem var(--tabs-color-overline),0 .0625rem var(--tabs-color-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.tabbed-content>:first-child{margin-top:0 !important}.tabbed-content>:last-child{margin-bottom:0 !important}.tabbed-content>.tabbed-set{margin:0}.tabbed-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.tabbed-set>input{opacity:0;position:absolute}.tabbed-set>input:checked+label{border-color:var(--tabs-color-label-active);color:var(--tabs-color-label-active)}.tabbed-set>input:checked+label+.tabbed-content{display:block}.tabbed-set>input:focus+label{outline-style:auto}.tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.tabbed-set>label{border-bottom:.125rem solid transparent;color:var(--tabs-color-label-inactive);cursor:pointer;font-size:var(--tabs-size-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .tabbed-set>label:hover{color:var(--tabs-color-label-active)} diff --git a/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css b/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css new file mode 100644 index 0000000..adc6166 --- /dev/null +++ b/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css @@ -0,0 +1,7 @@ +:root { +--tabs-color-label-active: hsla(231, 99%, 66%, 1); +--tabs-color-label-inactive: rgba(178, 206, 245, 0.62); +--tabs-color-overline: rgb(207, 236, 238); +--tabs-color-underline: rgb(207, 236, 238); +--tabs-size-label: 1rem; +} \ No newline at end of file diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt new file mode 100644 index 0000000..2ae9d74 --- /dev/null +++ b/_sources/api.rst.txt @@ -0,0 +1,86 @@ +.. _api: + +.. currentmodule:: kor + + +API +---------- + +The main **Kor** API is shown here: + + +.. autosummary:: + + create_extraction_chain + from_pydantic + + +Schema +====== + +Kor has its own internal representation of a schema. The schema +is pretty minimal and does not do much except for helping to produce +type descriptions for the prompts. + +Instead of using the internal representation it may be more convenient +to use **from_pydantic** to convert a pydantic schema into internal +representation automatically. + +.. note:: + It may be that the internal schema will be removed in the future in favor + of just using pydantic schema. + +.. autosummary:: + + Object + Text + Number + Bool + Selection + Option + + +Encoders +======== + +Encoders are used to specify how we want the extracted content to be +encoded. At the moment, JSONEncoder is the most flexible, the CSVEncoder +may be the most accurate, while the XMLEncoder may be neither. + +**create_extraction_chain** accepts an encoder as named argument allowing +a user to provide their own custom way to encode the input. + +.. autosummary:: + + JSONEncoder + CSVEncoder + XMLEncoder + +Base class: + +.. autosummary:: + + encoders.Encoder + encoders.SchemaBasedEncoder + +TypeDescriptors +================ + +.. autosummary:: + + TypeScriptDescriptor + BulletPointDescriptor + + +Base class: + +.. autosummary:: + + TypeDescriptor + + +Index +===== + +.. automodule:: generated.kor + diff --git a/_sources/apis.ipynb.txt b/_sources/apis.ipynb.txt new file mode 100644 index 0000000..dd79525 --- /dev/null +++ b/_sources/apis.ipynb.txt @@ -0,0 +1,858 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Natural Language Based APIs\n", + "\n", + "Being able to understand the content of text can help in tasks other than information extraction.\n", + "\n", + "Here, we'll see how extracting information from text can help with powering a natural language based assistant \n", + "that has different skills." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c719e4fc-3ccf-4633-a787-b2fe0d1eac65", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from langchain.chat_models import ChatOpenAI\n", + "from kor import create_extraction_chain, Object, Text, Number" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f1313c02-d415-4ce6-bff0-3df537cc06c2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + " max_tokens=2000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "bdd0f1af-55d4-4ab2-8932-b52a86450cdf", + "metadata": {}, + "source": [ + "## Control Music" + ] + }, + { + "cell_type": "markdown", + "id": "c6ce4726-db5b-49ee-abf7-780fd707be5f", + "metadata": {}, + "source": [ + "Here's a hypotehtical API for controlling music." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f61c94db-c05d-43ba-9ffc-b58552c715c3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"player\",\n", + " description=(\n", + " \"User is controlling a music player to select songs, pause or start them or play\"\n", + " \" music by a particular artist.\"\n", + " ),\n", + " attributes=[\n", + " Text(\n", + " id=\"song\",\n", + " description=\"User wants to play this song\",\n", + " examples=[],\n", + " many=True,\n", + " ),\n", + " Text(\n", + " id=\"album\",\n", + " description=\"User wants to play this album\",\n", + " examples=[],\n", + " many=True,\n", + " ),\n", + " Text(\n", + " id=\"artist\",\n", + " description=\"Music by the given artist\",\n", + " examples=[(\"Songs by paul simon\", \"paul simon\")],\n", + " many=True,\n", + " ),\n", + " Text(\n", + " id=\"action\",\n", + " description=\"Action to take one of: `play`, `stop`, `next`, `previous`.\",\n", + " examples=[\n", + " (\"Please stop the music\", \"stop\"),\n", + " (\"play something\", \"play\"),\n", + " (\"play a song\", \"play\"),\n", + " (\"next song\", \"next\"),\n", + " ],\n", + " ),\n", + " ],\n", + " many=False,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "49029ef7-c084-46f2-9791-6fb731252a9f", + "metadata": {}, + "source": [ + "**ATTENTION** Use the JSON encoder here rather than the default CSV encoder as it supports nested lists" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ff9ad27f-7a81-4123-8d0b-1e14802df67e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema, encoder_or_encoder_class=\"json\")" + ] + }, + { + "cell_type": "markdown", + "id": "e0b612d2-6893-4881-ad97-e09425511010", + "metadata": {}, + "source": [ + "## Music Player" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "760baa5f-9368-4b5a-abc0-6ac65c34b7a7", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'player': {'action': 'stop'}}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"stop the music now\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "462303c0-e83a-4e39-86cd-cab6875b40ef", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'player': {'action': 'play'}}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"i want to hear a song\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "02c7f1e5-1c8d-4e9f-82e6-c37a41d6de14", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'player': {'album': ['the lion king soundtrack']}}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"can you play the lion king soundtrack\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7a6d918c-53fe-426b-b37e-eec2abb8a704", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'data': {'player': {'artist': ['paul simon', 'led zeppelin', 'the doors']}},\n", + " 'raw': '{\"player\": {\"artist\": [\"paul simon\", \"led zeppelin\", \"the doors\"]}}',\n", + " 'errors': [],\n", + " 'validated_data': {}}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"play songs by paul simon and led zeppelin and the doors\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "b18acf0a-d99e-48de-ace5-fb01bded5a41", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'player': {'action': 'previous'}}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"could you play the previous song again?\")[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "4a90e50e-aa1b-45c6-920b-4589b424e561", + "metadata": {}, + "source": [ + "## Ticket ordering\n", + "\n", + "Here's an imaginary API for searching and buying tickets" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c50b080b-7179-4bbe-b234-83ce59e2d215", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"action\",\n", + " description=\"User is looking for sports tickets\",\n", + " attributes=[\n", + " Text(\n", + " id=\"sport\",\n", + " description=\"which sports do you want to buy tickets for?\",\n", + " examples=[\n", + " (\n", + " \"I want to buy tickets to basketball and football games\",\n", + " [\"basketball\", \"footbal\"],\n", + " )\n", + " ],\n", + " ),\n", + " Text(\n", + " id=\"location\",\n", + " description=\"where would you like to watch the game?\",\n", + " examples=[\n", + " (\"in boston\", \"boston\"),\n", + " (\"in france or italy\", [\"france\", \"italy\"]),\n", + " ],\n", + " ),\n", + " Object(\n", + " id=\"price_range\",\n", + " description=\"how much do you want to spend?\",\n", + " attributes=[],\n", + " examples=[\n", + " (\"no more than $100\", {\"price_max\": \"100\", \"currency\": \"$\"}),\n", + " (\n", + " \"between 50 and 100 dollars\",\n", + " {\"price_max\": \"100\", \"price_min\": \"50\", \"currency\": \"$\"},\n", + " ),\n", + " ],\n", + " ),\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "404e4f1a-d316-41f2-ab94-040e22001fc4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema, encoder_or_encoder_class=\"json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "73c31ace-32dd-4a33-ae39-475db6934f6d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'action': {'sport': 'baseball',\n", + " 'location': 'LA area',\n", + " 'price_range': {'price_max': '100', 'currency': '$'}}}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"I want to buy tickets for a baseball game in LA area under $100\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "78e3b3af-bfa8-4503-854a-b83a7f8f49e6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'action': {'sport': 'celtics',\n", + " 'location': 'boston',\n", + " 'price_range': {'price_min': '20', 'price_max': '40', 'currency': '$'}}}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"I want to see a celtics game in boston somewhere between 20 and 40 dollars per ticket\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "20ddd000-df00-4014-9433-fba85181ba46", + "metadata": {}, + "source": [ + "## Company Search\n", + "\n", + "**ATTENTION** This is a demo that shows how to build a complex schema to run a company search that matches different criteria.\n", + "\n", + "However, using this format for issuing database queries (e.g., by translating the JSON into SQL) will only works well for simple queries. \n", + "\n", + "There's a better way to leverage LLMs to issue database queries, and support for that may be added to the package in the future." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "2b0bcf09-a3ae-4a8a-9ce3-f86834ce6ca2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "company_name = Text(\n", + " id=\"company_name\",\n", + " description=\"what is the name of the company you want to find\",\n", + " many=True,\n", + " examples=[\n", + " (\"Apple inc\", \"Apple inc\"),\n", + " (\"largest 10 banks in the world\", \"\"),\n", + " (\"microsoft and apple\", \"microsoft,apple\"),\n", + " ],\n", + ")\n", + "\n", + "industry_name = Text(\n", + " id=\"industry_name\",\n", + " description=\"what is the name of the company's industry\",\n", + " many=True,\n", + " examples=[\n", + " (\"companies in the steel manufacturing industry\", \"steel manufacturing\"),\n", + " (\"large banks\", \"banking\"),\n", + " (\"military companies\", \"defense\"),\n", + " (\"chinese companies\", \"\"),\n", + " (\"companies that cell cigars\", \"cigars\"),\n", + " ],\n", + ")\n", + "\n", + "geography_name = Text(\n", + " id=\"geography_name\",\n", + " description=\"where is the company based?\",\n", + " examples=[\n", + " (\"chinese companies\", \"china\"),\n", + " (\"companies based in france\", \"france\"),\n", + " (\"LaMaple was based in france, italy\", [\"france\", \"italy\"]),\n", + " (\"italy\", \"\"),\n", + " ],\n", + ")\n", + "\n", + "foundation_date = Text(\n", + " id=\"foundation_date\",\n", + " description=\"Foundation date of the company\",\n", + " examples=[(\"companies founded in 2023\", \"2023\")],\n", + ")\n", + "\n", + "attribute_filter = Object(\n", + " id=\"attribute_filter\",\n", + " many=True,\n", + " description=(\n", + " \"Filter by a value of an attribute using a binary expression. Specify the\"\n", + " \" attribute's name, an operator (>, <, =, !=, >=, <=, in, not in) and a value.\"\n", + " ),\n", + " attributes=[],\n", + " examples=[\n", + " (\n", + " \"Companies with revenue > 100\",\n", + " {\n", + " \"attribute\": \"revenue\",\n", + " \"op\": \">\",\n", + " \"value\": \"100\",\n", + " },\n", + " ),\n", + " (\n", + " \"number of employees between 50 and 1000\",\n", + " {\"attribute\": \"employees\", \"op\": \"in\", \"value\": [\"50\", \"1000\"]},\n", + " ),\n", + " (\n", + " \"blue or green color\",\n", + " {\n", + " \"attribute\": \"color\",\n", + " \"op\": \"in\",\n", + " \"value\": [\"blue\", \"green\"],\n", + " },\n", + " ),\n", + " (\n", + " \"companies that do not sell in california\",\n", + " {\n", + " \"attribute\": \"geography-sales\",\n", + " \"op\": \"not in\",\n", + " \"value\": \"california\",\n", + " },\n", + " ),\n", + " ],\n", + ")\n", + "\n", + "sales_geography = Text(\n", + " id=\"geography_sales\",\n", + " description=\"where is the company doing sales? Please use a single country name.\",\n", + " many=True,\n", + " examples=[\n", + " (\"companies with sales in france\", \"france\"),\n", + " (\"companies that sell their products in germany\", \"germany\"),\n", + " (\"france, italy\", \"\"),\n", + " ],\n", + ")\n", + "\n", + "attribute_selection_block = Text(\n", + " id=\"attribute_selection\",\n", + " description=\"Asking to see the value of one or more attributes\",\n", + " many=True,\n", + " examples=[\n", + " (\"What is the revenue of tech companies?\", \"revenue\"),\n", + " (\"market cap of apple?\", \"market cap\"),\n", + " (\"number of employees of largest company\", \"number of employees\"),\n", + " (\"what are the revenue and market cap of apple\", [\"revenue\", \"market cap\"]),\n", + " (\n", + " \"share price and number of shares of indian companies\",\n", + " [\"share price\", \"number of shares\"],\n", + " ),\n", + " ],\n", + ")\n", + "\n", + "sort_by_attribute_block = Object(\n", + " id=\"sort_block\",\n", + " description=(\n", + " \"Use to request to sort the results by a particular attribute. \"\n", + " \"Can specify the direction\"\n", + " ),\n", + " attributes=[\n", + " Text(id=\"direction\", description=\"The direction of the sort\"),\n", + " Text(id=\"attribute\", description=\"The sort attribute\"),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"Largest by market-cap tech companies\",\n", + " {\"direction\": \"descending\", \"attribute\": \"market-cap\"},\n", + " ),\n", + " (\n", + " \"sort by companies with smallest revenue \",\n", + " {\"direction\": \"ascending\", \"attribute\": \"revenue\"},\n", + " ),\n", + " ],\n", + ")\n", + "\n", + "schema = Object(\n", + " id=\"search_for_companies\",\n", + " description=\"Search for companies matching the following criteria.\",\n", + " attributes=[\n", + " company_name,\n", + " geography_name,\n", + " foundation_date,\n", + " industry_name,\n", + " sales_geography,\n", + " attribute_filter,\n", + " attribute_selection_block,\n", + " sort_by_attribute_block,\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "ee6725a8-246b-4163-a657-5f3eddbf5d2b", + "metadata": {}, + "source": [ + "**ATTENTION** Some of the queries below fail. One common reason is that more examples could be useful to show the model how to group objects together. Pay attention to failures!" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "7b389d20-ae6b-4764-9209-3cd3c2f0a715", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema, encoder_or_encoder_class=\"json\")" + ] + }, + { + "cell_type": "markdown", + "id": "3c59de74-1cb6-4644-9bd9-526669dd7fa4", + "metadata": {}, + "source": [ + "Confirm that we're not getting **false** positives" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "b203ac4a-4f9f-45c6-a509-39b9a6cfd98f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = (\n", + " \"Today Alice MacDonald is turning sixty days old. She had blue eyes. \"\n", + " \"Bob is turning 10 years old. His eyes were bright red.\"\n", + ")\n", + "chain.run(text)[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "398377bf-5d30-4b4c-b637-e9af969d16a4", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'search_for_companies': {'attribute_filter': [{'attribute': 'market cap',\n", + " 'op': '>',\n", + " 'value': '1 million'},\n", + " {'attribute': 'employees', 'op': 'in', 'value': ['20', '50']}],\n", + " 'attribute_selection': ['revenue', 'eps']}}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = (\n", + " \"revenue, eps of indian companies that have market cap of over 1 million, and\"\n", + " \" and between 20-50 employees\"\n", + ")\n", + "chain.run(text)[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2a620246-4c85-4256-8f58-0acbcc9455a3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'search_for_companies': {'attribute_filter': [{'attribute': 'building_color',\n", + " 'op': 'in',\n", + " 'value': ['red', 'blue']}]}}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = \"companies that own red and blue buildings\"\n", + "chain.run(text)[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "4745517e-507e-4d1a-97e0-d143fa34cea2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'search_for_companies': {'geography_name': 'germany',\n", + " 'sort_block': {'direction': 'descending',\n", + " 'attribute': 'number of employees'},\n", + " 'attribute_selection': ['revenue']}}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = \"revenue of largest german companies sorted by number of employees\"\n", + "chain.run(text)[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "b206407f-57e0-4212-8e75-970cb49b52e5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'search_for_companies': {'attribute_filter': [{'attribute': 'market cap',\n", + " 'op': '>',\n", + " 'value': '1000000'},\n", + " {'attribute': 'building color', 'op': 'in', 'value': ['red', 'blue']}],\n", + " 'attribute_selection': ['revenue', 'eps']}}" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = (\n", + " \"revenue, eps of indian companies that have market cap of over 1 million, \"\n", + " \"that own red and blue buildings\"\n", + ")\n", + "chain.run(text)[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a1025f99-eb0a-4d96-923e-35f36e4ac6b2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "search_for_companies: { // Search for companies matching the following criteria.\n", + " company_name: Array // what is the name of the company you want to find\n", + " geography_name: string // where is the company based?\n", + " foundation_date: string // Foundation date of the company\n", + " industry_name: Array // what is the name of the company's industry\n", + " geography_sales: Array // where is the company doing sales? Please use a single country name.\n", + " attribute_filter: Array<{ // Filter by a value of an attribute using a binary expression. Specify the attribute's name, an operator (>, <, =, !=, >=, <=, in, not in) and a value.\n", + " }>\n", + " attribute_selection: Array // Asking to see the value of one or more attributes\n", + " sort_block: { // Use to request to sort the results by a particular attribute. Can specify the direction\n", + " direction: string // The direction of the sort\n", + " attribute: string // The sort attribute\n", + " }\n", + "}\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in JSON format. Do not output anything except for the extracted information. Do not add any clarifying information. Do not add any fields that are not in the schema. If the text contains attributes that do not appear in the schema, please ignore them. All output must be in JSON format and follow the schema specified above. Wrap the JSON in tags.\n", + "\n", + "\n", + "\n", + "Input: Apple inc\n", + "Output: {\"search_for_companies\": {\"company_name\": [\"Apple inc\"]}}\n", + "Input: largest 10 banks in the world\n", + "Output: {}\n", + "Input: microsoft and apple\n", + "Output: {\"search_for_companies\": {\"company_name\": [\"microsoft,apple\"]}}\n", + "Input: chinese companies\n", + "Output: {\"search_for_companies\": {\"geography_name\": \"china\"}}\n", + "Input: companies based in france\n", + "Output: {\"search_for_companies\": {\"geography_name\": \"france\"}}\n", + "Input: LaMaple was based in france, italy\n", + "Output: {\"search_for_companies\": {\"geography_name\": [\"france\", \"italy\"]}}\n", + "Input: italy\n", + "Output: {}\n", + "Input: companies founded in 2023\n", + "Output: {\"search_for_companies\": {\"foundation_date\": \"2023\"}}\n", + "Input: companies in the steel manufacturing industry\n", + "Output: {\"search_for_companies\": {\"industry_name\": [\"steel manufacturing\"]}}\n", + "Input: large banks\n", + "Output: {\"search_for_companies\": {\"industry_name\": [\"banking\"]}}\n", + "Input: military companies\n", + "Output: {\"search_for_companies\": {\"industry_name\": [\"defense\"]}}\n", + "Input: chinese companies\n", + "Output: {}\n", + "Input: companies that cell cigars\n", + "Output: {\"search_for_companies\": {\"industry_name\": [\"cigars\"]}}\n", + "Input: companies with sales in france\n", + "Output: {\"search_for_companies\": {\"geography_sales\": [\"france\"]}}\n", + "Input: companies that sell their products in germany\n", + "Output: {\"search_for_companies\": {\"geography_sales\": [\"germany\"]}}\n", + "Input: france, italy\n", + "Output: {}\n", + "Input: Companies with revenue > 100\n", + "Output: {\"search_for_companies\": {\"attribute_filter\": [{\"attribute\": \"revenue\", \"op\": \">\", \"value\": \"100\"}]}}\n", + "Input: number of employees between 50 and 1000\n", + "Output: {\"search_for_companies\": {\"attribute_filter\": [{\"attribute\": \"employees\", \"op\": \"in\", \"value\": [\"50\", \"1000\"]}]}}\n", + "Input: blue or green color\n", + "Output: {\"search_for_companies\": {\"attribute_filter\": [{\"attribute\": \"color\", \"op\": \"in\", \"value\": [\"blue\", \"green\"]}]}}\n", + "Input: companies that do not sell in california\n", + "Output: {\"search_for_companies\": {\"attribute_filter\": [{\"attribute\": \"geography-sales\", \"op\": \"not in\", \"value\": \"california\"}]}}\n", + "Input: What is the revenue of tech companies?\n", + "Output: {\"search_for_companies\": {\"attribute_selection\": [\"revenue\"]}}\n", + "Input: market cap of apple?\n", + "Output: {\"search_for_companies\": {\"attribute_selection\": [\"market cap\"]}}\n", + "Input: number of employees of largest company\n", + "Output: {\"search_for_companies\": {\"attribute_selection\": [\"number of employees\"]}}\n", + "Input: what are the revenue and market cap of apple\n", + "Output: {\"search_for_companies\": {\"attribute_selection\": [\"revenue\", \"market cap\"]}}\n", + "Input: share price and number of shares of indian companies\n", + "Output: {\"search_for_companies\": {\"attribute_selection\": [\"share price\", \"number of shares\"]}}\n", + "Input: Largest by market-cap tech companies\n", + "Output: {\"search_for_companies\": {\"sort_block\": {\"direction\": \"descending\", \"attribute\": \"market-cap\"}}}\n", + "Input: sort by companies with smallest revenue \n", + "Output: {\"search_for_companies\": {\"sort_block\": {\"direction\": \"ascending\", \"attribute\": \"revenue\"}}}\n", + "Input: [user_input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(\"[user_input]\").to_string())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/document_extraction.ipynb.txt b/_sources/document_extraction.ipynb.txt new file mode 100644 index 0000000..eec73a9 --- /dev/null +++ b/_sources/document_extraction.ipynb.txt @@ -0,0 +1,1021 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Document Extraction\n", + "\n", + "Here, we'll be extracting content from a longer document.\n", + "\n", + "\n", + "The basic workflow is the following:\n", + "\n", + "1. Load the document\n", + "2. Clean up the document (optional)\n", + "3. Split the document into chunks\n", + "4. Extract from *every* chunk of text\n", + "\n", + "-------------\n", + "\n", + "**ATTENTION** This is a *brute force* workflow -- there will be an LLM call for every piece of text that is being analyzed. \n", + "This can be **expensive** 💰💰💰, so use at your own risk and monitor your costs!\n", + "\n", + "---------------\n", + "\n", + "Let's apply this workflow to an HTML file.\n", + "\n", + "We'll reduce HTML to markdown. This is a lossy step, which can sometimes improve extraction results, and sometimes make extraction worse.\n", + "\n", + "When scraping HTML, executing javascript may be necessary to get all HTML fully rendered. \n", + "\n", + "Here's a piece of code that can execute javascript using playwright: \n", + "\n", + "\n", + "```python\n", + "async def a_download_html(url: str, extra_sleep: int) -> str:\n", + " \"\"\"Download an HTML from a URL.\n", + " \n", + " In some pathological cases, an extra sleep period may be needed.\n", + " \"\"\"\n", + "\n", + " async with async_playwright() as p:\n", + " browser = await p.chromium.launch()\n", + " page = await browser.new_page()\n", + " await page.goto(url, wait_until=\"load\")\n", + " if extra_sleep:\n", + " await asyncio.sleep(extra_sleep)\n", + " html_content = await page.content()\n", + " await browser.close()\n", + " return html_content\n", + "```\n", + "\n", + "Another possibility is to use: https://python.langchain.com/en/latest/modules/indexes/document_loaders/examples/url.html#selenium-url-loader\n", + "\n", + "---------\n", + " \n", + "Again this can be **expensive** 💰💰💰, so use at your own risk and monitor your costs!" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f8536314-f0f3-4bb9-acd6-f2cec4046380", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d93b3de7-9b81-456e-acff-4b0df9755c14", + "metadata": { + "nbsphinx": "hidden", + "tags": [] + }, + "outputs": [], + "source": [ + "from typing import List, Optional\n", + "import itertools\n", + "import requests\n", + "\n", + "import pandas as pd\n", + "from pydantic import BaseModel, Field, validator\n", + "from kor import extract_from_documents, from_pydantic, create_extraction_chain\n", + "from kor.documents.html import MarkdownifyHTMLProcessor\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.schema import Document\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter" + ] + }, + { + "cell_type": "markdown", + "id": "725a851e-ab91-4aa4-94b5-747bbf096460", + "metadata": {}, + "source": [ + "## LLM\n", + "\n", + "Instantiate an LLM. \n", + "\n", + "Try experimenting with the cheaper davinci models or with gpt-3.5-turbo before trying the more expensive davinci-003 or gpt 4.\n", + "\n", + "In some cases, providing a better prompt (with more examples) can help make up for using a smaller model." + ] + }, + { + "cell_type": "markdown", + "id": "b2aeb931-4725-4ab8-956e-18420d1c9a36", + "metadata": { + "tags": [] + }, + "source": [ + "\n", + "-------------------\n", + "\n", + "Quality can vary a **lot** depending on which LLM is used and how many examples are provided.\n", + "\n", + "-------------------" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "fab20ada-6443-4799-b6e8-faf16a2fb585", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Using gpt-3.5-turbo which is pretty cheap, but has worse quality\n", + "llm = ChatOpenAI(temperature=0)" + ] + }, + { + "cell_type": "markdown", + "id": "cd9eaffc-875d-4b2c-a189-6c7c181fe628", + "metadata": {}, + "source": [ + "## Schema" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "981938c5-f438-49a0-b511-329d31073a56", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class ShowOrMovie(BaseModel):\n", + " name: str = Field(\n", + " description=\"The name of the movie or tv show\",\n", + " )\n", + " season: Optional[str] = Field(\n", + " description=\"Season of TV show. Extract as a digit stripping Season prefix.\",\n", + " )\n", + " year: Optional[str] = Field(\n", + " description=\"Year when the movie / tv show was released\",\n", + " )\n", + " latest_episode: Optional[str] = Field(\n", + " description=\"Date when the latest episode was released\",\n", + " )\n", + " link: Optional[str] = Field(description=\"Link to the movie / tv show.\")\n", + "\n", + " # rating -- not included because rating on rottentomatoes is in the html elements\n", + " # you could try extracting it by using the raw HTML (rather than markdown)\n", + " # or you could try doing something similar on imdb\n", + "\n", + " @validator(\"name\")\n", + " def name_must_not_be_empty(cls, v):\n", + " if not v:\n", + " raise ValueError(\"Name must not be empty\")\n", + " return v\n", + "\n", + "\n", + "schema, extraction_validator = from_pydantic(\n", + " ShowOrMovie,\n", + " description=\"Extract information about popular movies/tv shows including their name, year, link and rating.\",\n", + " examples=[\n", + " (\n", + " \"[Rain Dogs Latest Episode: Apr 03](/tv/rain_dogs)\",\n", + " {\"name\": \"Rain Dogs\", \"latest_episode\": \"Apr 03\", \"link\": \"/tv/rain_dogs\"},\n", + " )\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ff57507d-d789-4ae3-8763-0465e8b27686", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(\n", + " llm,\n", + " schema,\n", + " encoder_or_encoder_class=\"csv\",\n", + " validator=extraction_validator,\n", + " input_formatter=\"triple_quotes\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "65a2ff9e-951a-46f8-8cb5-d3eab0c28f59", + "metadata": {}, + "source": [ + "## Download\n", + "\n", + "Let's download a page containing movies from my favorite movie review site." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b5bd49b1-0b51-40ff-b34b-3ad7f90423b6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "url = \"https://www.rottentomatoes.com/browse/tv_series_browse/sort:popular\"\n", + "response = requests.get(url) # Please see comment at top about using Selenium or" + ] + }, + { + "cell_type": "markdown", + "id": "1226d70c-68ad-49b5-8327-3132a556bbf3", + "metadata": {}, + "source": [ + "Remember that in some cases you will need to execute javascript! Here's a snippet\n", + "\n", + "```python\n", + "from langchain.document_loaders import SeleniumURLLoader\n", + "document = SeleniumURLLoader(url).load()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "1963c139-169a-4d07-a2bd-cb2e7dfa171b", + "metadata": {}, + "source": [ + "## Extract\n", + "\n", + "Use langchain building blocks to assemble whatever pipeline you need for your own purposes." + ] + }, + { + "cell_type": "markdown", + "id": "8d4d40c9-6c9b-431d-9bd4-66a00f3de36f", + "metadata": {}, + "source": [ + "Create a langchain document with the HTML content." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "396a16b7-bc45-4035-9848-f995cddbba2f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "doc = Document(page_content=response.text)" + ] + }, + { + "cell_type": "markdown", + "id": "524e1105-f053-4954-9e11-e693820b4823", + "metadata": {}, + "source": [ + "Convert to markdown\n", + "\n", + "**ATTENTION** This step is lossy and may end up removing information that's relevant for extraction. You can always try pushing the raw HTML through if you're not worried about cost." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "22d3229a-aa6f-4586-a527-6f7835800740", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "md = MarkdownifyHTMLProcessor().process(doc)" + ] + }, + { + "cell_type": "markdown", + "id": "d98a7554-a3c7-42ea-99a4-d1e44aa9e22c", + "metadata": {}, + "source": [ + "Break the document to chunks so it fits in context window" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "814e4151-f7d7-412d-beab-58ed190b7dd3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "split_docs = RecursiveCharacterTextSplitter().split_documents([md])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e663f031-7a61-4a27-b925-1c9a6f365bcc", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Watch the trailer for You\n", + "\n", + "[You\n", + "\n", + " Latest Episode: Mar 09](/tv/you)\n", + "\n", + "Watch the trailer for She-Hulk: Attorney at Law\n", + "\n", + "[She-Hulk: Attorney at Law](/tv/she_hulk_attorney_at_law)\n", + "\n", + "[Breaking Bad](/tv/breaking_bad)\n", + "\n", + "Watch the trailer for The Lord of the Rings: The Rings of Power\n", + "\n", + "[The Lord of the Rings: The Rings of Power](/tv/the_lord_of_the_rings_the_rings_of_power)\n", + "\n", + "No results\n", + "\n", + " Reset Filters\n", + "\n", + " Load more\n", + "\n", + "Close video\n", + "\n", + "See Details\n", + "\n", + "See Details\n", + "\n", + "* [Help](/help_desk)\n", + "* [About Rotten Tomatoes](/about)\n", + "* [What's the Tomatometer®?](/about#whatisthetomatometer)\n", + "* \n", + "\n", + "* [Critic Submission](/critics/criteria)\n", + "* [Licensing](/help_desk/licensing)\n", + "* [Advertise With Us](https://together.nbcuni.com/advertise/?utm_source=rotten_tomatoes&utm_medium=referral&utm_campaign=property_ad_pages&utm_content=footer)\n", + "* [Careers](//www.fandango.com/careers)\n", + "\n", + "Join The Newsletter\n", + "\n", + "Get the freshest reviews, news, and more delivered right to your inbox!\n", + "\n", + "Join The Newsletter\n", + "[Join The Newsletter](https://optout.services.fandango.com/rottentomatoes)\n", + "\n", + "Follow Us\n", + "\n", + "* \n", + "* \n", + "* \n", + "* \n", + "* \n", + "\n", + "Copyright © Fandango. All rights reserved.\n", + "\n", + "Join Newsletter\n", + "[Join Newsletter](https://optout.services.fandango.com/rottentomatoes)\n", + "* [Privacy Policy](//www.fandango.com/policies/privacy-policy)\n", + "* [Terms and Policies](//www.fandango.com/policies/terms-and-policies)\n", + "* [Cookie Settings](javascript:void(0))\n", + "* [California Notice](//www.fandango.com/californianotice)\n", + "* [Ad Choices](//www.fandango.com/policies/cookies-and-tracking#cookie_management)\n", + "* \n", + "* [Accessibility](/faq#accessibility)\n", + "\n", + "* V3.1\n", + "* [Privacy Policy](//www.fandango.com/policies/privacy-policy)\n", + "* [Terms and Policies](//www.fandango.com/policies/terms-and-policies)\n", + "* [Cookie Settings](javascript:void(0))\n", + "* [California Notice](//www.fandango.com/californianotice)\n", + "* [Ad Choices](//www.fandango.com/policies/cookies-and-tracking#cookie_management)\n", + "* [Accessibility](/faq#accessibility)\n", + "\n", + "Copyright © Fandango. All rights reserved.\n" + ] + } + ], + "source": [ + "print(split_docs[-1].page_content)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ec72cb5b-1fcb-4381-85e8-f060ea1f0077", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(split_docs)" + ] + }, + { + "cell_type": "markdown", + "id": "de953c9a-cb03-4ac8-8ccd-a32bde1f5f61", + "metadata": {}, + "source": [ + "Run extraction" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1d17ebaa-8222-48df-82d9-42173a60f5f7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from langchain.callbacks import get_openai_callback" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "bdb85b12-25b9-477c-bf7e-5407812f4807", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total Tokens: 5854\n", + "Prompt Tokens: 5128\n", + "Completion Tokens: 726\n", + "Successful Requests: 4\n", + "Total Cost (USD): $0.011708000000000001\n" + ] + } + ], + "source": [ + "with get_openai_callback() as cb:\n", + " document_extraction_results = await extract_from_documents(\n", + " chain, split_docs, max_concurrency=5, use_uid=False, return_exceptions=True\n", + " )\n", + " print(f\"Total Tokens: {cb.total_tokens}\")\n", + " print(f\"Prompt Tokens: {cb.prompt_tokens}\")\n", + " print(f\"Completion Tokens: {cb.completion_tokens}\")\n", + " print(f\"Successful Requests: {cb.successful_requests}\")\n", + " print(f\"Total Cost (USD): ${cb.total_cost}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d00f86ed-48c3-46c3-8d37-49de50817d93", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "validated_data = list(\n", + " itertools.chain.from_iterable(\n", + " extraction[\"validated_data\"] for extraction in document_extraction_results\n", + " )\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "89e35b77-aac4-4a32-9515-9ebe9bfef046", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(validated_data)" + ] + }, + { + "cell_type": "markdown", + "id": "4b5f6bb8-656f-4d92-b9d7-3dfce538705b", + "metadata": {}, + "source": [ + "Extraction is not perfect, but you can use a better LLM or provide more examples!" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "75f3e35e-d6a9-4c0d-a5c3-a509eaf7d6ec", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nameseasonyearlatest_episodelink
0Beef1/tv/beef/s01
1Dave3/tv/dave/s03
2Schmigadoon!2/tv/schmigadoon/s02
3Pretty Baby: Brooke Shields1/tv/pretty_baby_brooke_shields/s01
4Tiny Beautiful Things1/tv/tiny_beautiful_things/s01
5Grease: Rise of the Pink Ladies1/tv/grease_rise_of_the_pink_ladies/s01
6Jury Duty1/tv/jury_duty/s01
7The Crossover1/tv/the_crossover/s01
8Transatlantic1/tv/transatlantic/s01
9Race to Survive: Alaska1/tv/race_to_survive_alaska/s01
10BeefApr 06/tv/beef
11The Night AgentMar 23/tv/the_night_agent
12UnstableMar 30/tv/unstable
13The MandalorianApr 05/tv/the_mandalorian
14The Big Door PrizeApr 05/tv/the_big_door_prize
15Class of '07Mar 17/tv/class_of_07
16Rabbit HoleApr 02/tv/rabbit_hole
17The PowerApr 07/tv/the_power
18The Last of UsMar 12/tv/the_last_of_us
19YellowjacketsMar 31/tv/yellowjackets
20SuccessionApr 02/tv/succession
21Lucky HankApr 02/tv/lucky_hank
22Sex/LifeMar 02/tv/sex_life
23Ted LassoApr 05/tv/ted_lasso
24WellmaniaMar 29/tv/wellmania
25Daisy Jones & the SixMar 24/tv/daisy_jones_and_the_six
26Shadow and BoneMar 16/tv/shadow_and_bone
27The Order/tv/the_order
28ShrinkingMar 24/tv/shrinking
29SwarmMar 17/tv/swarm
30The Last Kingdom/tv/the_last_kingdom
31Rain DogsApr 03/tv/rain_dogs
32ExtrapolationsApr 07/tv/extrapolations
33War SailorApr 02/tv/war_sailor
34YouMar 09/tv/you
35She-Hulk: Attorney at Law/tv/she_hulk_attorney_at_law
36YouMar 09/tv/you
37She-Hulk: Attorney at LawNone/tv/she_hulk_attorney_at_law
38Breaking BadNone/tv/breaking_bad
39The Lord of the Rings: The Rings of PowerNone/tv/the_lord_of_the_rings_the_rings_of_power
\n", + "
" + ], + "text/plain": [ + " name season year latest_episode \\\n", + "0 Beef 1 \n", + "1 Dave 3 \n", + "2 Schmigadoon! 2 \n", + "3 Pretty Baby: Brooke Shields 1 \n", + "4 Tiny Beautiful Things 1 \n", + "5 Grease: Rise of the Pink Ladies 1 \n", + "6 Jury Duty 1 \n", + "7 The Crossover 1 \n", + "8 Transatlantic 1 \n", + "9 Race to Survive: Alaska 1 \n", + "10 Beef Apr 06 \n", + "11 The Night Agent Mar 23 \n", + "12 Unstable Mar 30 \n", + "13 The Mandalorian Apr 05 \n", + "14 The Big Door Prize Apr 05 \n", + "15 Class of '07 Mar 17 \n", + "16 Rabbit Hole Apr 02 \n", + "17 The Power Apr 07 \n", + "18 The Last of Us Mar 12 \n", + "19 Yellowjackets Mar 31 \n", + "20 Succession Apr 02 \n", + "21 Lucky Hank Apr 02 \n", + "22 Sex/Life Mar 02 \n", + "23 Ted Lasso Apr 05 \n", + "24 Wellmania Mar 29 \n", + "25 Daisy Jones & the Six Mar 24 \n", + "26 Shadow and Bone Mar 16 \n", + "27 The Order \n", + "28 Shrinking Mar 24 \n", + "29 Swarm Mar 17 \n", + "30 The Last Kingdom \n", + "31 Rain Dogs Apr 03 \n", + "32 Extrapolations Apr 07 \n", + "33 War Sailor Apr 02 \n", + "34 You Mar 09 \n", + "35 She-Hulk: Attorney at Law \n", + "36 You Mar 09 \n", + "37 She-Hulk: Attorney at Law None \n", + "38 Breaking Bad None \n", + "39 The Lord of the Rings: The Rings of Power None \n", + "\n", + " link \n", + "0 /tv/beef/s01 \n", + "1 /tv/dave/s03 \n", + "2 /tv/schmigadoon/s02 \n", + "3 /tv/pretty_baby_brooke_shields/s01 \n", + "4 /tv/tiny_beautiful_things/s01 \n", + "5 /tv/grease_rise_of_the_pink_ladies/s01 \n", + "6 /tv/jury_duty/s01 \n", + "7 /tv/the_crossover/s01 \n", + "8 /tv/transatlantic/s01 \n", + "9 /tv/race_to_survive_alaska/s01 \n", + "10 /tv/beef \n", + "11 /tv/the_night_agent \n", + "12 /tv/unstable \n", + "13 /tv/the_mandalorian \n", + "14 /tv/the_big_door_prize \n", + "15 /tv/class_of_07 \n", + "16 /tv/rabbit_hole \n", + "17 /tv/the_power \n", + "18 /tv/the_last_of_us \n", + "19 /tv/yellowjackets \n", + "20 /tv/succession \n", + "21 /tv/lucky_hank \n", + "22 /tv/sex_life \n", + "23 /tv/ted_lasso \n", + "24 /tv/wellmania \n", + "25 /tv/daisy_jones_and_the_six \n", + "26 /tv/shadow_and_bone \n", + "27 /tv/the_order \n", + "28 /tv/shrinking \n", + "29 /tv/swarm \n", + "30 /tv/the_last_kingdom \n", + "31 /tv/rain_dogs \n", + "32 /tv/extrapolations \n", + "33 /tv/war_sailor \n", + "34 /tv/you \n", + "35 /tv/she_hulk_attorney_at_law \n", + "36 /tv/you \n", + "37 /tv/she_hulk_attorney_at_law \n", + "38 /tv/breaking_bad \n", + "39 /tv/the_lord_of_the_rings_the_rings_of_power " + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame(record.dict() for record in validated_data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/generated/kor.documents.rst.txt b/_sources/generated/kor.documents.rst.txt new file mode 100644 index 0000000..f1e3e57 --- /dev/null +++ b/_sources/generated/kor.documents.rst.txt @@ -0,0 +1,29 @@ +kor.documents package +===================== + +Submodules +---------- + +kor.documents.html module +------------------------- + +.. automodule:: kor.documents.html + :members: + :undoc-members: + :show-inheritance: + +kor.documents.typedefs module +----------------------------- + +.. automodule:: kor.documents.typedefs + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: kor.documents + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/generated/kor.encoders.rst.txt b/_sources/generated/kor.encoders.rst.txt new file mode 100644 index 0000000..5898e45 --- /dev/null +++ b/_sources/generated/kor.encoders.rst.txt @@ -0,0 +1,61 @@ +kor.encoders package +==================== + +Submodules +---------- + +kor.encoders.csv\_data module +----------------------------- + +.. automodule:: kor.encoders.csv_data + :members: + :undoc-members: + :show-inheritance: + +kor.encoders.encode module +-------------------------- + +.. automodule:: kor.encoders.encode + :members: + :undoc-members: + :show-inheritance: + +kor.encoders.json\_data module +------------------------------ + +.. automodule:: kor.encoders.json_data + :members: + :undoc-members: + :show-inheritance: + +kor.encoders.typedefs module +---------------------------- + +.. automodule:: kor.encoders.typedefs + :members: + :undoc-members: + :show-inheritance: + +kor.encoders.utils module +------------------------- + +.. automodule:: kor.encoders.utils + :members: + :undoc-members: + :show-inheritance: + +kor.encoders.xml module +----------------------- + +.. automodule:: kor.encoders.xml + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: kor.encoders + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/generated/kor.extraction.rst.txt b/_sources/generated/kor.extraction.rst.txt new file mode 100644 index 0000000..1c61b77 --- /dev/null +++ b/_sources/generated/kor.extraction.rst.txt @@ -0,0 +1,37 @@ +kor.extraction package +====================== + +Submodules +---------- + +kor.extraction.api module +------------------------- + +.. automodule:: kor.extraction.api + :members: + :undoc-members: + :show-inheritance: + +kor.extraction.parser module +---------------------------- + +.. automodule:: kor.extraction.parser + :members: + :undoc-members: + :show-inheritance: + +kor.extraction.typedefs module +------------------------------ + +.. automodule:: kor.extraction.typedefs + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: kor.extraction + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/generated/kor.rst.txt b/_sources/generated/kor.rst.txt new file mode 100644 index 0000000..c9cb1d3 --- /dev/null +++ b/_sources/generated/kor.rst.txt @@ -0,0 +1,87 @@ +kor package +=========== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + kor.documents + kor.encoders + kor.extraction + +Submodules +---------- + +kor.adapters module +------------------- + +.. automodule:: kor.adapters + :members: + :undoc-members: + :show-inheritance: + +kor.examples module +------------------- + +.. automodule:: kor.examples + :members: + :undoc-members: + :show-inheritance: + +kor.exceptions module +--------------------- + +.. automodule:: kor.exceptions + :members: + :undoc-members: + :show-inheritance: + +kor.nodes module +---------------- + +.. automodule:: kor.nodes + :members: + :undoc-members: + :show-inheritance: + +kor.prompts module +------------------ + +.. automodule:: kor.prompts + :members: + :undoc-members: + :show-inheritance: + +kor.type\_descriptors module +---------------------------- + +.. automodule:: kor.type_descriptors + :members: + :undoc-members: + :show-inheritance: + +kor.validators module +--------------------- + +.. automodule:: kor.validators + :members: + :undoc-members: + :show-inheritance: + +kor.version module +------------------ + +.. automodule:: kor.version + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: kor + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/generated/modules.rst.txt b/_sources/generated/modules.rst.txt new file mode 100644 index 0000000..bf0bd38 --- /dev/null +++ b/_sources/generated/modules.rst.txt @@ -0,0 +1,7 @@ +kor +=== + +.. toctree:: + :maxdepth: 4 + + kor diff --git a/_sources/guidelines.ipynb.txt b/_sources/guidelines.ipynb.txt new file mode 100644 index 0000000..21c2702 --- /dev/null +++ b/_sources/guidelines.ipynb.txt @@ -0,0 +1,52 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c8f6fd5d-980b-4a1f-97cf-e5eff784f8f2", + "metadata": {}, + "source": [ + "# Guidelines\n", + "\n", + "`Kor` is a wrapper around LLMs to help with information extraction.\n", + "\n", + "The quality of the results depends on a lot of factors. \n", + "\n", + "Here are a few things to experiment with to improve quality:\n", + "\n", + "* Add more examples. Diverse examples can help, including examples where nothing should be extracted.\n", + "* Improve the descriptions of the attributes.\n", + "* If working with multi-paragraph text, specify an `input_formatter` of `\"triple_quotes\"` when creating the chain.\n", + "* Try a better model (e.g., text-davinci-003, gpt-4).\n", + "* Break the schema into a few smaller schemas, run separate extractions, and merge the results.\n", + "* If possible to flatten the schema, and use a CSV encoding instead of a JSON encoding.\n", + "* Add verification/correction steps (ask an LLM to correct or verify the results of the extraction).\n", + "\n", + "## Keep in mind! 😶‍🌫️\n", + "\n", + "* If you're extracting information from a **single** **structured** source (e.g., linkedin), using an LLM is not a good idea -- traditional web-scraping will be much cheaper and reliable.\n", + "* If perfect quality is needed, then even with all the hacks above, you'll need to plan on having a human in the loop as even the best LLMs will make mistakes with complex extraction tasks." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/index.md.txt b/_sources/index.md.txt new file mode 100644 index 0000000..245efe8 --- /dev/null +++ b/_sources/index.md.txt @@ -0,0 +1,209 @@ +# Kor + +This is a half-baked prototype that "helps" you extract structured data from text using LLMs 🧩. + +Specify the schema of what should be extracted and provide some examples. + +Kor will generate a prompt, send it to the specified LLM and parse out the +output. + +You might even get results back. + +So yes – it’s just another wrapper on top of LLMs with its own flavor of abstractions. 😸 + +See [documentation](https://eyurtsev.github.io/kor/). + +Integrated with the [LangChain framework 😽💗 🦜🔗](https://python.langchain.com/en/latest/index.html). + +## Kor style schema + +```python +from langchain.chat_models import ChatOpenAI +from kor import create_extraction_chain, Object, Text + +llm = ChatOpenAI( + model_name="gpt-3.5-turbo", + temperature=0, + max_tokens=2000, + model_kwargs = { + 'frequency_penalty':0, + 'presence_penalty':0, + 'top_p':1.0 + } +) + +schema = Object( + id="player", + description=( + "User is controlling a music player to select songs, pause or start them or play" + " music by a particular artist." + ), + attributes=[ + Text( + id="song", + description="User wants to play this song", + examples=[], + many=True, + ), + Text( + id="album", + description="User wants to play this album", + examples=[], + many=True, + ), + Text( + id="artist", + description="Music by the given artist", + examples=[("Songs by paul simon", "paul simon")], + many=True, + ), + Text( + id="action", + description="Action to take one of: `play`, `stop`, `next`, `previous`.", + examples=[ + ("Please stop the music", "stop"), + ("play something", "play"), + ("play a song", "play"), + ("next song", "next"), + ], + ), + ], + many=False, +) + +chain = create_extraction_chain(llm, schema, encoder_or_encoder_class='json') +chain.invoke("play songs by paul simon and led zeppelin and the doors")['data'] +``` + +```python +{'player': {'artist': ['paul simon', 'led zeppelin', 'the doors']}} +``` + +## Pydantic style schema + +* See documentation here [pydantic](https://eyurtsev.github.io/kor/validation.html). + +```python +class Action(enum.Enum): + play = "play" + stop = "stop" + previous = "previous" + next_ = "next" + + +class MusicRequest(BaseModel): + song: Optional[List[str]] = Field( + description="The song(s) that the user would like to be played." + ) + album: Optional[List[str]] = Field( + description="The album(s) that the user would like to be played." + ) + artist: Optional[List[str]] = Field( + description="The artist(s) whose music the user would like to hear.", + examples=[("Songs by paul simon", "paul simon")], + ) + action: Optional[Action] = Field( + description="The action that should be taken; one of `play`, `stop`, `next`, `previous`", + examples=[ + ("Please stop the music", "stop"), + ("play something", "play"), + ("play a song", "play"), + ("next song", "next"), + ], + ) + +schema, validator = from_pydantic(MusicRequest) +chain = create_extraction_chain( + llm, schema, encoder_or_encoder_class="json", validator=validator +) +chain.invoke("stop the music now")["validated_data"] +``` + +```python +MusicRequest(song=None, album=None, artist=None, action=) +``` + + + +## Compatibility + +`Kor` is tested against python 3.8, 3.9, 3.10, 3.11. + +## Installation + +```sh +pip install kor +``` + +## 💡 Ideas + +Ideas of some things that could be done with Kor. + +* Extract data from text that matches an extraction schema. +* Power an AI assistant with skills by precisely understanding a user request. +* Provide natural language access to an existing API. + +## 🚧 Prototype + +Prototype! So the API is not expected to be stable! + +## ✨ What does Kor excel at? 🌟 + +* Making mistakes! Plenty of them! +* Slow! It uses large prompts with examples, and works best with the larger slower LLMs. +* Crashing for long enough pieces of text! Context length window could become + limiting when working with large forms or long text inputs. + +The expectation is that as LLMs improve some of these issues will be mitigated. + +## Limitations + +Kor has no limitations. (Just kidding.) + +Take a look at the section above and at the compatibility section. + +## Got Ideas? + +Open an issue, and let's discuss! + +## 🎶 Why the name? + +Fast to type and sufficiently unique. + +## Contributing + +If you have any ideas or feature requests, please open an issue and share! + +See [CONTRIBUTING.md](https://github.com/eyurtsev/kor/blob/main/CONTRIBUTING.md) for more information. + +## Other packages + +Probabilistically speaking this package is unlikely to work for your use case. + +So here are some great alternatives: + +* [Promptify](https://github.com/promptslab/Promptify) +* [MiniChain](https://srush.github.io/MiniChain/examples/stats/) + + +```{toctree} +:maxdepth: 2 +:caption: Contents +tutorial +objects +nested_objects +untyped_objects +apis +validation +document_extraction +schema_serialization +guidelines +``` + +```{toctree} +:maxdepth: 2 +:caption: Advanced +prompt +type_descriptors +api +``` diff --git a/_sources/nested_objects.ipynb.txt b/_sources/nested_objects.ipynb.txt new file mode 100644 index 0000000..3de2aba --- /dev/null +++ b/_sources/nested_objects.ipynb.txt @@ -0,0 +1,354 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Nested Objects and Lists\n", + "\n", + "Kor attempts to make it easy to capture more complex structure during extraction.\n", + "\n", + "**ATTENTION** At the moment to use either nested objects or nested lists, one should use the `json` encoder." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "718c66a7-6186-4ed8-87e9-5ed28e3f209e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from kor.nodes import Object, Text, Number\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.llms import OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9bc98f35-ea5f-4b74-a32e-a300a22c0c89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + " max_tokens=2000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "c7e128c2-83a1-4c8e-b9af-8af0521214b9", + "metadata": {}, + "source": [ + "## Nested Objects\n", + "\n", + "Here, we'll introduce an `Address` object which will be neste inside of the main schema." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f75990e6-5973-4618-9f15-f3b60a14bfa5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from_address = Object(\n", + " id=\"from_address\",\n", + " description=\"Person moved away from this address\",\n", + " attributes=[\n", + " Text(id=\"street\"),\n", + " Text(id=\"city\"),\n", + " Text(id=\"state\"),\n", + " Text(id=\"zipcode\"),\n", + " Text(id=\"country\", description=\"A country in the world; e.g., France.\"),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"100 Main St, Boston, MA, 23232, USA\",\n", + " {\n", + " \"street\": \"100 Marlo St\",\n", + " \"city\": \"Boston\",\n", + " \"state\": \"MA\",\n", + " \"zipcode\": \"23232\",\n", + " \"country\": \"USA\",\n", + " },\n", + " )\n", + " ],\n", + ")\n", + "\n", + "to_address = from_address.replace(\n", + " id=\"to_address\", description=\"Address to which the person is moving\"\n", + ")\n", + "\n", + "schema = Object(\n", + " id=\"information\",\n", + " attributes=[\n", + " Text(\n", + " id=\"person_name\",\n", + " description=\"The full name of the person or partial name\",\n", + " examples=[(\"John Smith was here\", \"John Smith\")],\n", + " ),\n", + " from_address,\n", + " to_address,\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "e010d0e7-504f-401c-9ac9-53bea91908bf", + "metadata": {}, + "source": [ + "## JSON encoding\n", + "\n", + "To use nested objects, at least for now we have to swap to the JSON encoder.\n", + "\n", + "Anecdotally, CSV encoding seems to produce more robust extraction results, so JSON encoding may perform worse even though it's more flexible." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "54a199a5-24b4-442c-8907-1449e437a880", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"json\", input_formatter=None\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "193e257b-df01-45ec-af77-076d2070533b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'information': [{'person_name': 'Alice Doe',\n", + " 'from_address': {'city': 'New York'},\n", + " 'to_address': {'city': 'Boston', 'state': 'MA'}},\n", + " {'person_name': 'Bob Smith',\n", + " 'from_address': {'city': 'Boston', 'state': 'MA'},\n", + " 'to_address': {'city': 'New York'}}]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"Alice Doe moved from New York to Boston, MA while Bob Smith did the opposite.\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c8295f36-f986-4db2-97bc-ef2e6cdbcc87", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'information': [{'person_name': 'Alice Doe',\n", + " 'from_address': {'city': 'New York'},\n", + " 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Bob Smith',\n", + " 'from_address': {'city': 'New York'},\n", + " 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Andrew', 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Joana', 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Paul', 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Betty',\n", + " 'from_address': {'city': 'Boston'},\n", + " 'to_address': {'city': 'New York'}}]}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"Alice Doe and Bob Smith moved from New York to Boston. Andrew was 12 years\"\n", + " \" old. He also moved to Boston. So did Joana and Paul. Betty did the opposite.\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "3cec5163-0081-461d-84c5-078661121bda", + "metadata": {}, + "source": [ + "## Nested Lists" + ] + }, + { + "cell_type": "markdown", + "id": "68bcd9c3-7d8b-4bc3-b14a-b4b9f757c894", + "metadata": {}, + "source": [ + "Let's repeat the same schema as above, but let the address be a `many=True` field." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e528f20c-46d3-40b6-b1ba-11024002deb8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from_address = Object(\n", + " id=\"from_address\",\n", + " description=\"Person moved away from this address\",\n", + " attributes=[\n", + " Text(id=\"street\"),\n", + " Text(id=\"city\"),\n", + " Text(id=\"state\"),\n", + " Text(id=\"zipcode\"),\n", + " Text(id=\"country\", description=\"A country in the world; e.g., France.\"),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"100 Main St, Boston,MA, 23232, USA\",\n", + " {\n", + " \"street\": \"100 Marlo St\",\n", + " \"city\": \"Boston\",\n", + " \"state\": \"MA\",\n", + " \"zipcode\": \"23232\",\n", + " \"country\": \"USA\",\n", + " },\n", + " )\n", + " ],\n", + " many=True, # <-- PLEASE NOTE THIS CHANGE\n", + ")\n", + "\n", + "to_address = from_address.replace(\n", + " id=\"to_address\", description=\"Address to which the person is moving\"\n", + ")\n", + "\n", + "schema = Object(\n", + " id=\"information\",\n", + " attributes=[\n", + " Text(\n", + " id=\"person_name\",\n", + " description=\"The full name of the person or partial name\",\n", + " examples=[(\"John Smith was here\", \"John Smith\")],\n", + " ),\n", + " from_address,\n", + " to_address,\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "23b81b06-118a-4ebe-9e20-5df1bf269ce3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema, encoder_or_encoder_class=\"json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "29219fae-41cb-4235-92fa-07b16ded2296", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'information': [{'person_name': 'Alice Doe',\n", + " 'from_address': [{'city': 'New York'}],\n", + " 'to_address': [{'city': 'Boston'}]},\n", + " {'person_name': 'Bob Smith',\n", + " 'from_address': [{'city': 'New York'}],\n", + " 'to_address': [{'city': 'Boston'}, {'city': 'LA'}]}]}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"Alice Doe and Bob Smith moved from New York to Boston. Bob later moved to LA.\"\n", + ")[\"data\"]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/objects.ipynb.txt b/_sources/objects.ipynb.txt new file mode 100644 index 0000000..8c0ad3b --- /dev/null +++ b/_sources/objects.ipynb.txt @@ -0,0 +1,428 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Working With Objects\n", + "\n", + "Kor attempts to make it easy to extract objects from text." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "718c66a7-6186-4ed8-87e9-5ed28e3f209e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from kor.nodes import Object, Text, Number\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.llms import OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9bc98f35-ea5f-4b74-a32e-a300a22c0c89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + " max_tokens=2000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "5d3beab3-6dea-4301-8c59-ae1685830afa", + "metadata": {}, + "source": [ + "## Object Schema\n", + "\n", + "Kor the familiar idea of an `Object` type to specify how to extract an object from text." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3bb910e9-43c4-42dd-83dd-546b7df6e805", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"personal_info\",\n", + " description=\"Personal information about a given person.\",\n", + " attributes=[\n", + " Text(\n", + " id=\"first_name\",\n", + " description=\"The first name of the person\",\n", + " examples=[(\"John Smith went to the store\", \"John\")],\n", + " ),\n", + " Text(\n", + " id=\"last_name\",\n", + " description=\"The last name of the person\",\n", + " examples=[(\"John Smith went to the store\", \"Smith\")],\n", + " ),\n", + " Number(\n", + " id=\"age\",\n", + " description=\"The age of the person in years.\",\n", + " examples=[(\"23 years old\", \"23\"), (\"I turned three on sunday\", \"3\")],\n", + " ),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\",\n", + " [\n", + " {\"first_name\": \"John\", \"last_name\": \"Smith\", \"age\": 23},\n", + " {\"first_name\": \"Jane\", \"last_name\": \"Doe\", \"age\": 5},\n", + " ],\n", + " )\n", + " ],\n", + " many=True,\n", + ")\n", + "\n", + "\n", + "chain = create_extraction_chain(llm, schema)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ab82c5b9-37a5-46f2-8bfc-88e6fe6fc36b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "personal_info: Array<{ // Personal information about a given person.\n", + " first_name: string // The first name of the person\n", + " last_name: string // The last name of the person\n", + " age: number // The age of the person in years.\n", + "}>\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in CSV format in Excel dialect. Please use a | as the delimiter. \n", + " Do NOT add any clarifying information. Output MUST follow the schema above. Do NOT add any additional columns that do not appear in the schema.\n", + "\n", + "\n", + "\n", + "Input: John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\n", + "Output: first_name|last_name|age\n", + "John|Smith|23\n", + "Jane|Doe|5\n", + "\n", + "Input: John Smith went to the store\n", + "Output: first_name|last_name|age\n", + "John||\n", + "\n", + "Input: John Smith went to the store\n", + "Output: first_name|last_name|age\n", + "|Smith|\n", + "\n", + "Input: 23 years old\n", + "Output: first_name|last_name|age\n", + "||23\n", + "\n", + "Input: I turned three on sunday\n", + "Output: first_name|last_name|age\n", + "||3\n", + "\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "markdown", + "id": "d4899820-fc53-40aa-b38e-a4e8f7aa8a92", + "metadata": {}, + "source": [ + "Please note above that examples were specified on a per attribute level.\n", + "\n", + "When this works it allows one to more easily compose attributes; however, to improve\n", + "performance generally examples will need to be provided at the object level (as we'll do below), as it\n", + "helps the model determine how to associate attributes together." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "40d549b0-f676-4fa2-8d50-9e20f3f2d05f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'personal_info': [{'first_name': 'Eugene', 'last_name': '', 'age': '18'}]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"Eugene was 18 years old a long time ago.\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a875d378-2481-43ad-a8f6-673d17596175", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'personal_info': [{'first_name': 'Bob', 'last_name': 'Alice', 'age': ''}]}\n" + ] + } + ], + "source": [ + "chain = create_extraction_chain(llm, schema)\n", + "print(\n", + " chain.run(\n", + " \"My name is Bob Alice and my phone number is (123)-444-9999. I found my true love one\"\n", + " \" on a blue sunday. Her number was (333)1232832. Her name was Moana Sunrise and she was 10 years old.\"\n", + " )[\"data\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "d3a8a3c6-b7cf-40f1-b287-ae78141e6502", + "metadata": {}, + "source": [ + "And **nothing** should be extracted from the text below." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "8be30aa6-a095-4506-8ec9-bde84dd107d3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'personal_info': [{'first_name': '', 'last_name': '', 'age': ''}]}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"My phone number is (123)-444-9999. I found my true love one on a blue sunday.\"\n", + " \" Her number was (333)1232832\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "ea520ab9-38ae-4fc2-ab95-468df85f200e", + "metadata": {}, + "source": [ + "### Handling Hallucinations\n", + "\n", + "LLMs that don't understand instructions well will need more examples to perform well on extraction tasks.\n", + "\n", + "Let's comment some of the examples from the previous schema to see the outputs." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9a300e76-2f26-4914-b160-1d90548714a0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"personal_info\",\n", + " description=\"Personal information about a given person.\",\n", + " attributes=[\n", + " Text(\n", + " id=\"first_name\",\n", + " description=\"The first name of the person\",\n", + " # examples=[(\"John Smith went to the store\", \"John\")]\n", + " ),\n", + " Text(\n", + " id=\"last_name\",\n", + " description=\"The last name of the person\",\n", + " # examples=[(\"John Smith went to the store\", \"Smith\")],\n", + " ),\n", + " Number(\n", + " id=\"age\",\n", + " description=\"The age of the person in years.\",\n", + " # examples=[(\"23 years old\", \"23\"), (\"I turned three on sunday\", \"3\")]\n", + " ),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\",\n", + " [\n", + " {\"first_name\": \"John\", \"last_name\": \"Smith\", \"age\": 23},\n", + " {\"first_name\": \"Jane\", \"last_name\": \"Doe\", \"age\": 5},\n", + " ],\n", + " )\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "5c694d79-e72c-4712-b891-111bc0279032", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'personal_info': [{'first_name': 'Bob', 'last_name': 'Alice', 'age': ''},\n", + " {'first_name': 'Moana', 'last_name': 'Sunrise', 'age': '10'}]}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain = create_extraction_chain(llm, schema)\n", + "chain.run(\n", + " \"My name is Bob Alice and my phone number is (123)-444-9999. I found my true love one\"\n", + " \" on a blue sunday. Her number was (333)1232832. Her name was Moana Sunrise and she was 10 years old.\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "8d5e4bcc-1fe5-4bdd-b1e2-00e0c7577cbb", + "metadata": {}, + "source": [ + "### What's the actual prompt?" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "a2944e8c-4630-4b29-b505-b2ca6fceba01", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "personal_info: Array<{ // Personal information about a given person.\n", + " first_name: string // The first name of the person\n", + " last_name: string // The last name of the person\n", + " age: number // The age of the person in years.\n", + "}>\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in CSV format in Excel dialect. Please use a | as the delimiter. \n", + " Do NOT add any clarifying information. Output MUST follow the schema above. Do NOT add any additional columns that do not appear in the schema.\n", + "\n", + "\n", + "\n", + "Input: John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\n", + "Output: first_name|last_name|age\n", + "John|Smith|23\n", + "Jane|Doe|5\n", + "\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/prompt.ipynb.txt b/_sources/prompt.ipynb.txt new file mode 100644 index 0000000..51afe95 --- /dev/null +++ b/_sources/prompt.ipynb.txt @@ -0,0 +1,285 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6fcfbb4c-e91d-46aa-8653-38f094146c0c", + "metadata": {}, + "source": [ + "# Custom Prompt\n", + "\n", + "Here, we'll see how to customize the instruction segment of the **Kor** prompt." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5419b2f8-1c28-497d-9bf0-a046d21a93d9", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "import pprint\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6dfe32e7-e80c-46d8-b173-eb9fe7d66e87", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from kor.nodes import Object, Text, Number\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.prompts import PromptTemplate" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "96ed58c4-45d2-4236-a6a5-8b894f4b601c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + ")\n", + "\n", + "schema = Object(\n", + " id=\"person\",\n", + " description=\"Personal information\",\n", + " examples=[\n", + " (\"Alice and Bob are friends\", [{\"first_name\": \"Alice\"}, {\"first_name\": \"Bob\"}])\n", + " ],\n", + " attributes=[\n", + " Text(\n", + " id=\"first_name\",\n", + " description=\"The first name of a person.\",\n", + " )\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "d4acce29-6720-40dc-b74e-86fcaf3db29d", + "metadata": {}, + "source": [ + "## Create a template" + ] + }, + { + "cell_type": "markdown", + "id": "0ee0a720-90de-4563-9d5e-76c663d6d5c7", + "metadata": {}, + "source": [ + "Here we create an instruction template. \n", + "\n", + "The template accepts 2 optional parameters:\n", + "\n", + "1. `type_description` -- will be replaced with the schema type-descriptor.\n", + "2. `format_instructions` -- will be replaced with the format instructions of whichever encoder is used." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ebc251dd-e7aa-4859-8385-ca32c7fd900c", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Pep talk for your LLM goes here]\n", + "\n", + "Add some type description\n", + "\n", + "```TypeScript\n", + "\n", + "person: Array<{ // Personal information\n", + " first_name: string // The first name of a person.\n", + "}>\n", + "```\n", + "\n", + "\n", + "Add some format instructions\n", + "\n", + "Please output the extracted information in CSV format in Excel dialect. Please use a | as the delimiter. \n", + " Do NOT add any clarifying information. Output MUST follow the schema above. Do NOT add any additional columns that do not appear in the schema.\n", + "Suffix heren\n", + "\n", + "\n", + "Input: Alice and Bob are friends\n", + "Output: first_name\n", + "Alice\n", + "Bob\n", + "\n", + "Input: hello\n", + "Output:\n" + ] + } + ], + "source": [ + "instruction_template = PromptTemplate(\n", + " input_variables=[\"format_instructions\", \"type_description\"],\n", + " template=(\n", + " \"[Pep talk for your LLM goes here]\\n\\n\"\n", + " \"Add some type description\\n\\n\"\n", + " \"{type_description}\\n\\n\" # Can comment out\n", + " \"Add some format instructions\\n\\n\"\n", + " \"{format_instructions}\\n\"\n", + " \"Suffix heren\\n\"\n", + " ),\n", + ")\n", + "\n", + "\n", + "chain = create_extraction_chain(llm, schema, instruction_template=instruction_template)\n", + "\n", + "print(chain.prompt.format_prompt(text=\"hello\").to_string())" + ] + }, + { + "cell_type": "markdown", + "id": "08581bc7-a134-40b7-a17b-ec8bd85de3f9", + "metadata": {}, + "source": [ + "## Custom Encoder and TypeDescriptor" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e406eac6-da5b-4d13-8378-cee5cfbbf544", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor import JSONEncoder, TypeDescriptor" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "65ae257b-983c-496c-87d2-8c59ff4f9fda", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class CatEncoder(JSONEncoder):\n", + " def get_instruction_segment(self) -> str:\n", + " return \"Encode your response as Cat JSON enclosed in <😼> tags.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "86611975-41c8-41d4-9347-7e3f4ae5247f", + "metadata": {}, + "outputs": [], + "source": [ + "class CatType(TypeDescriptor):\n", + " def describe(self, node: Object) -> str:\n", + " \"\"\"Describe the schema of the node.\"\"\"\n", + " return f\"A 😼 ate the schema of {type(node)} 😼\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "9658425e-684a-46db-98e3-85dfda6ca97e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Pep talk for your LLM goes here]\n", + "\n", + "Add some type description\n", + "\n", + "A 😼 ate the schema of 😼\n", + "\n", + "Add some format instructions\n", + "\n", + "Encode your response as Cat JSON enclosed in <😼> tags.\n", + "Suffix heren\n", + "\n", + "\n", + "Input: Alice and Bob are friends\n", + "Output: {\"person\": [{\"first_name\": \"Alice\"}, {\"first_name\": \"Bob\"}]}\n", + "Input: hello\n", + "Output:\n" + ] + } + ], + "source": [ + "instruction_template = PromptTemplate(\n", + " input_variables=[\"format_instructions\", \"type_description\"],\n", + " template=(\n", + " \"[Pep talk for your LLM goes here]\\n\\n\"\n", + " \"Add some type description\\n\\n\"\n", + " \"{type_description}\\n\\n\" # Can comment out\n", + " \"Add some format instructions\\n\\n\"\n", + " \"{format_instructions}\\n\"\n", + " \"Suffix heren\\n\"\n", + " ),\n", + ")\n", + "\n", + "\n", + "chain = create_extraction_chain(\n", + " llm,\n", + " schema,\n", + " instruction_template=instruction_template,\n", + " encoder_or_encoder_class=CatEncoder,\n", + " type_descriptor=CatType(),\n", + ")\n", + "\n", + "print(chain.prompt.format_prompt(text=\"hello\").to_string())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/schema_serialization.ipynb.txt b/_sources/schema_serialization.ipynb.txt new file mode 100644 index 0000000..0ac6e44 --- /dev/null +++ b/_sources/schema_serialization.ipynb.txt @@ -0,0 +1,306 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Schema serialization\n", + "\n", + "A Kor schema can be serialized and deserialzed to JSON. This lets you store the schema outside of the code.\n", + "\n", + "**ATTENTION** This only works with pydantic v1 at the moment." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "47a11a37", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.nodes import Object, Text, Number" + ] + }, + { + "cell_type": "markdown", + "id": "ac403159", + "metadata": {}, + "source": [ + "## Serialization\n", + "\n", + "To serialize a schema just call the `json()` method on the schema" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "67cb9713", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"id\": \"personal_info\", \"description\": \"Personal information about a given person.\", \"many\": true, \"attributes\": [{\"id\": \"first_name\", \"description\": \"The first name of the person\", \"many\": false, \"examples\": [[\"John Smith went to the store\", \"John\"]], \"$type\": \"Text\"}, {\"id\": \"last_name\", \"description\": \"The last name of the person\", \"many\": false, \"examples\": [[\"John Smith went to the store\", \"Smith\"]], \"$type\": \"Text\"}, {\"id\": \"age\", \"description\": \"The age of the person in years.\", \"many\": false, \"examples\": [[\"23 years old\", \"23\"], [\"I turned three on sunday\", \"3\"]], \"$type\": \"Number\"}], \"examples\": [[\"John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\", [{\"first_name\": \"John\", \"last_name\": \"Smith\", \"age\": 23}, {\"first_name\": \"Jane\", \"last_name\": \"Doe\", \"age\": 5}]]]}\n" + ] + } + ], + "source": [ + "schema = Object(\n", + " id=\"personal_info\",\n", + " description=\"Personal information about a given person.\",\n", + " attributes=[\n", + " Text(\n", + " id=\"first_name\",\n", + " description=\"The first name of the person\",\n", + " examples=[(\"John Smith went to the store\", \"John\")],\n", + " ),\n", + " Text(\n", + " id=\"last_name\",\n", + " description=\"The last name of the person\",\n", + " examples=[(\"John Smith went to the store\", \"Smith\")],\n", + " ),\n", + " Number(\n", + " id=\"age\",\n", + " description=\"The age of the person in years.\",\n", + " examples=[(\"23 years old\", \"23\"), (\"I turned three on sunday\", \"3\")],\n", + " ),\n", + " ],\n", + " examples=[\n", + " (\n", + " \"John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\",\n", + " [\n", + " {\"first_name\": \"John\", \"last_name\": \"Smith\", \"age\": 23},\n", + " {\"first_name\": \"Jane\", \"last_name\": \"Doe\", \"age\": 5},\n", + " ],\n", + " )\n", + " ],\n", + " many=True,\n", + ")\n", + "\n", + "print(schema.json())" + ] + }, + { + "cell_type": "markdown", + "id": "11712477", + "metadata": {}, + "source": [ + "## Deserialization\n", + "\n", + "Kor lets you define the schema in JSON. The structure of the JSON matches the struture of the `Object` type.\n", + "\n", + "The following attribute types must be annotated with a type descrimintator (`$type`):\n", + "\n", + "- Number\n", + "- Text\n", + "- Bool\n", + "- Selection" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3bd33817", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "json = \"\"\"\n", + "{\n", + " \"id\": \"personal_info\",\n", + " \"description\": \"Personal information about a given person.\",\n", + " \"attributes\": [\n", + " {\n", + " \"$type\": \"Text\",\n", + " \"id\": \"first_name\",\n", + " \"description\": \"The first name of the person\",\n", + " \"examples\": [[\"John Smith went to the store\", \"John\"]]\n", + " },\n", + " {\n", + " \"$type\": \"Text\",\n", + " \"id\": \"last_name\",\n", + " \"description\": \"The last name of the person\",\n", + " \"examples\": [[\"John Smith went to the store\", \"Smith\"]]\n", + " },\n", + " {\n", + " \"$type\": \"Number\",\n", + " \"id\": \"age\",\n", + " \"description\": \"The age of the person in years.\",\n", + " \"examples\": [[\"23 years old\", \"23\"], [\"I turned three on sunday\", \"3\"]]\n", + " }\n", + " ],\n", + " \"examples\": [\n", + " [\n", + " \"John Smith was 23 years old. He was very tall. He knew Jane Doe. She was 5 years old.\",\n", + " [\n", + " {\"first_name\": \"John\", \"last_name\": \"Smith\", \"age\": 23},\n", + " {\"first_name\": \"Jane\", \"last_name\": \"Doe\", \"age\": 5}\n", + " ]\n", + " ]\n", + " ],\n", + " \"many\": true\n", + "}\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "3581b713", + "metadata": {}, + "source": [ + "To deserialize a schema from JSON simply call the `parse_raw()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6088c98a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object.parse_raw(json)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "718c66a7-6186-4ed8-87e9-5ed28e3f209e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from langchain.chat_models import ChatOpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9bc98f35-ea5f-4b74-a32e-a300a22c0c89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + " max_tokens=2000,\n", + " model_kwargs={\"frequency_penalty\": 0, \"presence_penalty\": 0, \"top_p\": 1.0},\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "54a199a5-24b4-442c-8907-1449e437a880", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "193e257b-df01-45ec-af77-076d2070533b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'personal_info': [{'first_name': 'Eugene', 'last_name': '', 'age': '18'}]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"Eugene was 18 years old a long time ago.\")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c8295f36-f986-4db2-97bc-ef2e6cdbcc87", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'personal_info': [{'first_name': 'Bob', 'last_name': 'Alice', 'age': ''}]}\n" + ] + } + ], + "source": [ + "chain = create_extraction_chain(llm, schema)\n", + "print(\n", + " chain.run(\n", + " \"My name is Bob Alice and my phone number is (123)-444-9999. I found my true love one\"\n", + " \" on a blue sunday. Her number was (333)1232832. Her name was Moana Sunrise and she was 10 years old.\"\n", + " )[\"data\"]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/tutorial.ipynb.txt b/_sources/tutorial.ipynb.txt new file mode 100644 index 0000000..9094bac --- /dev/null +++ b/_sources/tutorial.ipynb.txt @@ -0,0 +1,394 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6fcfbb4c-e91d-46aa-8653-38f094146c0c", + "metadata": {}, + "source": [ + "# Introduction\n", + "\n", + "**Kor** is a thin wrapper on top of LLMs that helps to extract structured data using LLMs. \n", + "\n", + "To use Kor, specify the schema of what should be extracted and provide some extraction examples.\n", + "\n", + "As you're looking through this tutorial, examine 👀 the outputs carefully to understand what errors are being made.\n", + "\n", + "Extraction isn't perfect! Understand the limitations before adopting it for your use case." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5419b2f8-1c28-497d-9bf0-a046d21a93d9", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "import pprint\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "718c66a7-6186-4ed8-87e9-5ed28e3f209e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from kor.nodes import Object, Text, Number\n", + "from langchain.chat_models import ChatOpenAI" + ] + }, + { + "cell_type": "markdown", + "id": "6645f896-c969-444d-b9f2-85318abb79d6", + "metadata": {}, + "source": [ + "## Schema\n", + "\n", + "Kor requires that you specify the `schema` of what you want parsed with some optional examples.\n", + "\n", + "We'll start off by specifying a **very simple** schema. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "cfb6e83c-ed20-470a-9316-b5919416d6b1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"person\",\n", + " description=\"Personal information\",\n", + " examples=[\n", + " (\"Alice and Bob are friends\", [{\"first_name\": \"Alice\"}, {\"first_name\": \"Bob\"}])\n", + " ],\n", + " attributes=[\n", + " Text(\n", + " id=\"first_name\",\n", + " description=\"The first name of a person.\",\n", + " )\n", + " ],\n", + " many=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "35a8348b-6bed-4506-9bac-843137261b5f", + "metadata": {}, + "source": [ + "The schema above consists of a single object node which contains a single text attribute called **first_name**.\n", + "\n", + "The object can be repeated many times, so if the text contains many multiple first names, multiple objects will be extracted.\n", + "\n", + "As part of the schema, we specified a `description` of what we're extracting, as well as 2 examples.\n", + "\n", + "Including both a `description` and `examples` will likely improve performance." + ] + }, + { + "cell_type": "markdown", + "id": "65de393b-838e-4bf5-a3b7-a14a394bb4d9", + "metadata": {}, + "source": [ + "## Langchain\n", + "\n", + "Instantiate a langchain LLM and create a chain.\n", + "\n", + "https://langchain.readthedocs.io/en/latest/modules/llms.html" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a655001e-8268-478b-b841-48ee8fa30ec1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from langchain.llms import OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "faafb3d1-cc7c-4a24-9578-a2a997d42868", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + " max_tokens=2000,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a1ffd515-d035-4965-8661-ac0b58fb0215", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema)" + ] + }, + { + "cell_type": "markdown", + "id": "a6849441-f9ae-468d-9003-b26bfa0253dd", + "metadata": { + "tags": [] + }, + "source": [ + "## Extract\n", + "\n", + "With a `chain` and a `schema` defined, we're ready to extract data." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a8c66cd5-05d3-4f61-b06c-38b27ee79c33", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'person': [{'first_name': 'Bobby'}, {'first_name': 'Joe'}]}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run((\"My name is Bobby. My brother's name Joe.\"))[\"data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "16611e52-735c-45a8-b495-1fa1adf0ce9f", + "metadata": {}, + "source": [ + "We got back a list of people (under the `person` key)." + ] + }, + { + "cell_type": "markdown", + "id": "684bcda8-b110-4362-8cea-dd2a7213e71d", + "metadata": {}, + "source": [ + "### The Full Response\n", + "\n", + "The full response contains the raw output from the LLM, and a list of errors of any errors that occurred while\n", + "parsing the LLM result." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1d7c4f21-4770-4d48-a4ad-0e58b82a8fa6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'data': {'person': [{'first_name': 'Bobby'}, {'first_name': 'Joe'}]},\n", + " 'raw': 'first_name\\nBobby\\nJoe',\n", + " 'errors': [],\n", + " 'validated_data': {}}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run((\"My name is Bobby. My brother's name Joe.\"))" + ] + }, + { + "cell_type": "markdown", + "id": "65773928-027c-4340-a635-969b41f73de2", + "metadata": {}, + "source": [ + "## The Prompt\n", + "\n", + "And here's the actual prompt that was sent to the LLM." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "3c8a9239-6b00-4b53-865a-c9cb76834095", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "person: Array<{ // Personal information\n", + " first_name: string // The first name of a person.\n", + "}>\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in CSV format in Excel dialect. Please use a | as the delimiter. \n", + " Do NOT add any clarifying information. Output MUST follow the schema above. Do NOT add any additional columns that do not appear in the schema.\n", + "\n", + "\n", + "\n", + "Input: Alice and Bob are friends\n", + "Output: first_name\n", + "Alice\n", + "Bob\n", + "\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "markdown", + "id": "eb0a7aa0-e12b-4b14-b7f3-e8809e37508e", + "metadata": { + "tags": [] + }, + "source": [ + "## With pydantic" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "955d56c6-4d99-4bae-bdb2-8e80303229ec", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor import from_pydantic\n", + "from typing import List, Optional\n", + "from pydantic import BaseModel, Field" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "88ca1a62-5fe8-4c08-b73f-e568806dbe1a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Person(BaseModel):\n", + " first_name: str = Field(description=\"The first name of a person\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c69deb96-84bd-457a-9203-3b20b8ee4ac3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(\n", + " Person,\n", + " description=\"Personal Information\", # <-- Description\n", + " examples=[ # <-- Object level examples\n", + " (\"Alice and Bob are friends\", [{\"first_name\": \"Alice\"}, {\"first_name\": \"Bob\"}])\n", + " ],\n", + " many=True, # <-- Note Many = True\n", + ")\n", + "\n", + "chain = create_extraction_chain(llm, schema, validator=validator)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6724520e-9f09-4d5e-a054-7179a7d8e3ca", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'data': {'person': [{'first_name': 'Bobby'}, {'first_name': 'Joe'}]},\n", + " 'raw': 'first_name\\nBobby\\nJoe',\n", + " 'errors': [],\n", + " 'validated_data': [Person(first_name='Bobby'), Person(first_name='Joe')]}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run((\"My name is Bobby. My brother's name Joe.\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/type_descriptors.ipynb.txt b/_sources/type_descriptors.ipynb.txt new file mode 100644 index 0000000..9c8dbd4 --- /dev/null +++ b/_sources/type_descriptors.ipynb.txt @@ -0,0 +1,346 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Type Descriptors\n", + "\n", + "Let's explore type-descriptors for a bit.\n", + "\n", + "Many LLMs are somewhat finicky, and a slightly better phrased prompt may help improve results. So if you want\n", + "to use your own type-descriptions, you can define a custom one and pass it as an argument when creating an extraction chain.\n", + "\n", + "At the moment, Kor only uses a very limited number of internal types. There's no way to represent a `Union` or even a `Boolean`. For the time being use a `Text` node (or `str` in pydnatic) to capture more complex / missing types." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c719e4fc-3ccf-4633-a787-b2fe0d1eac65", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import enum\n", + "from typing import Optional, List\n", + "\n", + "from kor import from_pydantic\n", + "from pydantic import BaseModel, Field" + ] + }, + { + "cell_type": "markdown", + "id": "3a59195d-bdef-47ad-a568-0984ada9259a", + "metadata": {}, + "source": [ + "## Let's define a schema" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "fface268-cda5-430e-a0dc-c354ee4cfe2f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Action(enum.Enum):\n", + " play = \"play\"\n", + " stop = \"stop\"\n", + " previous = \"previous\"\n", + " next_ = \"next\"\n", + "\n", + "\n", + "class MusicRequest(BaseModel):\n", + " song: Optional[List[str]] = Field(\n", + " description=\"The song(s) that the user would like to be played.\"\n", + " )\n", + " album: Optional[List[str]] = Field(\n", + " description=\"The album(s) that the user would like to be played.\"\n", + " )\n", + " artist: Optional[List[str]] = Field(\n", + " description=\"The artist(s) whose music the user would like to hear.\",\n", + " examples=[(\"Songs by paul simon\", \"paul simon\")],\n", + " )\n", + " action: Optional[Action] = Field(\n", + " description=\"The action that should be taken; one of `play`, `stop`, `next`, `previous`\",\n", + " examples=[\n", + " (\"Please stop the music\", \"stop\"),\n", + " (\"play something\", \"play\"),\n", + " (\"play a song\", \"play\"),\n", + " (\"next song\", \"next\"),\n", + " ],\n", + " )\n", + " volume: Optional[float] = Field(\n", + " description=\"Set the volume\",\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4fe1ec70-1428-4433-acac-c190674a666e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(MusicRequest, description=\"Music recorder\")" + ] + }, + { + "cell_type": "markdown", + "id": "5472725a-95ec-4601-acd0-7e87890a6360", + "metadata": {}, + "source": [ + "## TypeScript" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8301c624-6933-4cd5-b5b6-1640c19ff32b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor import TypeScriptDescriptor" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "42e007b7-7aab-4468-9793-7e7514bea98e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "descriptor = TypeScriptDescriptor()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "99ed0af7-b608-4b46-96fa-ea9798113760", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "```TypeScript\n", + "\n", + "musicrequest: { // Music recorder\n", + " song: Array // The song(s) that the user would like to be played.\n", + " album: Array // The album(s) that the user would like to be played.\n", + " artist: Array // The artist(s) whose music the user would like to hear.\n", + " action: \"play\" | \"stop\" | \"previous\" | \"next\" // The action that should be taken; one of `play`, `stop`, `next`, `previous`\n", + " volume: number // Set the volume\n", + "}\n", + "```\n", + "\n" + ] + } + ], + "source": [ + "print(descriptor.describe(schema))" + ] + }, + { + "cell_type": "markdown", + "id": "1618bc04-ea40-4fdb-837f-e85e266299dd", + "metadata": {}, + "source": [ + "## BulletPoint" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "de9683ac-e5b3-46b2-a456-6beb7a5f38aa", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor import BulletPointDescriptor" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "19fd08fb-0098-46c8-a540-9d998bc6ee16", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "descriptor = BulletPointDescriptor()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c0788a1d-8eb7-442b-be98-1680501befae", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* musicrequest: Object # Music recorder\n", + "* song: Text # The song(s) that the user would like to be played.\n", + "* album: Text # The album(s) that the user would like to be played.\n", + "* artist: Text # The artist(s) whose music the user would like to hear.\n", + "* action: Selection # The action that should be taken; one of `play`, `stop`, `next`, `previous`\n", + "* volume: Number # Set the volume\n" + ] + } + ], + "source": [ + "print(descriptor.describe(schema))" + ] + }, + { + "cell_type": "markdown", + "id": "5b213137-cdb4-4309-ba2e-3b6bf716a2e2", + "metadata": {}, + "source": [ + "## Custom\n", + "\n", + "Here's an example on how to define your own type-description." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "966b3818-b591-41f5-b70e-fb51415bc3ae", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from typing import Any" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6f7526ff-0ee0-4a17-8478-36e1c4445ca7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor import TypeScriptDescriptor, Object\n", + "from kor.nodes import AbstractSchemaNode" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "93ad957a-7d6f-4ad3-b824-384cca1aa682", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class MeowDescriptor(TypeScriptDescriptor):\n", + " def visit_default(self, node: \"AbstractSchemaNode\", **kwargs: Any) -> List[str]:\n", + " \"\"\"Default action for a node.\"\"\"\n", + " depth = kwargs[\"depth\"]\n", + " space = \" \" + depth * \" ~(^._.)\" + \" \"\n", + " return [f\"{space}{node.id}: {node.__class__.__name__} # {node.description}\"]\n", + "\n", + " def visit_object(self, node: Object, **kwargs: Any) -> List[str]:\n", + " \"\"\"Visit an object node.\"\"\"\n", + " depth = kwargs[\"depth\"]\n", + " code_lines = self.visit_default(node, depth=depth)\n", + " for child in node.attributes:\n", + " code_lines.extend(child.accept(self, depth=depth + 1))\n", + " return code_lines\n", + "\n", + " def describe(self, node: Object) -> str:\n", + " \"\"\"Describe the type of the given node.\"\"\"\n", + " code_lines = node.accept(self, depth=0)\n", + " return \"\\n\".join(code_lines)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "225782dd-20c7-4d96-b10c-57bc8dceb683", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " musicrequest: Object # Music recorder\n", + " ~(^._.) song: Text # The song(s) that the user would like to be played.\n", + " ~(^._.) album: Text # The album(s) that the user would like to be played.\n", + " ~(^._.) artist: Text # The artist(s) whose music the user would like to hear.\n", + " ~(^._.) action: Selection # The action that should be taken; one of `play`, `stop`, `next`, `previous`\n", + " ~(^._.) volume: Number # Set the volume\n" + ] + } + ], + "source": [ + "print(MeowDescriptor().describe(schema))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/untyped_objects.ipynb.txt b/_sources/untyped_objects.ipynb.txt new file mode 100644 index 0000000..7af97ba --- /dev/null +++ b/_sources/untyped_objects.ipynb.txt @@ -0,0 +1,198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "## Untyped Obects 🤷\n", + "\n", + "It's possible to provide just examples without type information. It may be that the quality of results won't be affected significantly, if one adds sufficient examples to compensate for lack of information about the schema." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "718c66a7-6186-4ed8-87e9-5ed28e3f209e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from kor.extraction import create_extraction_chain\n", + "from kor.nodes import Object, Text, Number\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.llms import OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9bc98f35-ea5f-4b74-a32e-a300a22c0c89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4325ac08-248f-4c57-bca9-478f8cab0436", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema = Object(\n", + " id=\"information\",\n", + " attributes=[],\n", + " examples=[\n", + " (\n", + " \"John Smith moved to Boston from New York. Billy moved to LA.\",\n", + " [\n", + " {\n", + " \"person_name\": \"John Smith\",\n", + " \"from_address\": {\"city\": \"New York\"},\n", + " \"to_address\": {\"city\": \"Boston\"},\n", + " },\n", + " {\"person_name\": \"Billy\", \"to_address\": {\"city\": \"LA\"}},\n", + " ],\n", + " )\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ea83896d-be3a-44fb-b74c-ccb2b96e2a7e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(llm, schema, encoder_or_encoder_class=\"json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "82c52f44-657e-45fb-8dc0-80155ae63a86", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'information': [{'person_name': 'Alice Doe',\n", + " 'from_address': {'city': 'New York'},\n", + " 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Bob Smith',\n", + " 'from_address': {'city': 'New York'},\n", + " 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Andrew', 'to_address': {'city': 'Boston'}, 'age': 12},\n", + " {'person_name': 'Joana', 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Paul', 'to_address': {'city': 'Boston'}},\n", + " {'person_name': 'Betty',\n", + " 'from_address': {'city': 'Boston'},\n", + " 'to_address': {'city': 'New York'}}]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"Alice Doe and Bob Smith moved from New York to Boston. Andrew was 12 years\"\n", + " \" old. He also moved to Boston. So did Joana and Paul. Betty did the opposite.\"\n", + ")[\"data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "215eea94-148d-4955-8e17-c5f8d2030b4e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "information: { // \n", + "}\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in JSON format. Do not output anything except for the extracted information. Do not add any clarifying information. Do not add any fields that are not in the schema. If the text contains attributes that do not appear in the schema, please ignore them. All output must be in JSON format and follow the schema specified above. Wrap the JSON in tags.\n", + "\n", + "\n", + "\n", + "Input: John Smith moved to Boston from New York. Billy moved to LA.\n", + "Output: {\"information\": [{\"person_name\": \"John Smith\", \"from_address\": {\"city\": \"New York\"}, \"to_address\": {\"city\": \"Boston\"}}, {\"person_name\": \"Billy\", \"to_address\": {\"city\": \"LA\"}}]}\n", + "Input: [user_input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(\"[user_input]\").to_string())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_sources/validation.ipynb.txt b/_sources/validation.ipynb.txt new file mode 100644 index 0000000..451667d --- /dev/null +++ b/_sources/validation.ipynb.txt @@ -0,0 +1,926 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b3a0584-b52c-4873-abb8-8382e13ff5c0", + "metadata": {}, + "source": [ + "# Validation with Pydantic\n", + "\n", + "Here, we'll see how to use pydantic to specify the schema and validate the results.\n", + "\n", + "**ATTENTION** Validation does *NOT* imply that extraction was correct. Validation only implies that the\n", + "data was returned in the correct shape and meets all validation criteria. This doesn't mean\n", + "that the LLM didn't make some up information!" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0b4597b2-2a43-4491-8830-bf9f79428074", + "metadata": { + "nbsphinx": "hidden", + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "\n", + "sys.path.insert(0, \"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c719e4fc-3ccf-4633-a787-b2fe0d1eac65", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import enum\n", + "from langchain.chat_models import ChatOpenAI\n", + "from kor import create_extraction_chain, Object, Text, Number\n", + "import pydantic\n", + "from typing import List\n", + "from kor import from_pydantic\n", + "from pydantic import BaseModel, Field\n", + "from typing import Optional" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f1313c02-d415-4ce6-bff0-3df537cc06c2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(\n", + " model_name=\"gpt-3.5-turbo\",\n", + " temperature=0,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "c6ce4726-db5b-49ee-abf7-780fd707be5f", + "metadata": {}, + "source": [ + "Let's returning to our hypothetical music player API:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fface268-cda5-430e-a0dc-c354ee4cfe2f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Action(enum.Enum):\n", + " play = \"play\"\n", + " stop = \"stop\"\n", + " previous = \"previous\"\n", + " next_ = \"next\"\n", + "\n", + "\n", + "class MusicRequest(BaseModel):\n", + " song: Optional[List[str]] = Field(\n", + " default=None, description=\"The song(s) that the user would like to be played.\"\n", + " )\n", + " album: Optional[List[str]] = Field(\n", + " default=None, description=\"The album(s) that the user would like to be played.\"\n", + " )\n", + " artist: Optional[List[str]] = Field(\n", + " default=None,\n", + " description=\"The artist(s) whose music the user would like to hear.\",\n", + " examples=[(\"Songs by paul simon\", \"paul simon\")],\n", + " )\n", + " action: Optional[Action] = Field(\n", + " default=None,\n", + " description=\"The action that should be taken; one of `play`, `stop`, `next`, `previous`\",\n", + " examples=[\n", + " (\"Please stop the music\", \"stop\"),\n", + " (\"play something\", \"play\"),\n", + " (\"play a song\", \"play\"),\n", + " (\"next song\", \"next\"),\n", + " ],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4fe1ec70-1428-4433-acac-c190674a666e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(MusicRequest)" + ] + }, + { + "cell_type": "markdown", + "id": "49029ef7-c084-46f2-9791-6fb731252a9f", + "metadata": {}, + "source": [ + "**ATTENTION** Use the JSON encoder here rather than the default CSV encoder as it supports nested lists" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ff9ad27f-7a81-4123-8d0b-1e14802df67e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"json\", validator=validator\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "3cc3f196-5c63-44ae-bbf3-471c2af47bf8", + "metadata": {}, + "source": [ + "Let's test it out" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "248fa47a-18b5-414f-a656-31c88f7a8dc4", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "musicrequest: { // \n", + " song: Array // The song(s) that the user would like to be played.\n", + " album: Array // The album(s) that the user would like to be played.\n", + " artist: Array // The artist(s) whose music the user would like to hear.\n", + " action: \"play\" | \"stop\" | \"previous\" | \"next\" // The action that should be taken; one of `play`, `stop`, `next`, `previous`\n", + "}\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in JSON format. Do not output anything except for the extracted information. Do not add any clarifying information. Do not add any fields that are not in the schema. If the text contains attributes that do not appear in the schema, please ignore them. All output must be in JSON format and follow the schema specified above. Wrap the JSON in tags.\n", + "\n", + "\n", + "\n", + "Input: Songs by paul simon\n", + "Output: {\"musicrequest\": {\"artist\": [\"paul simon\"]}}\n", + "Input: Please stop the music\n", + "Output: {\"musicrequest\": {\"action\": \"stop\"}}\n", + "Input: play something\n", + "Output: {\"musicrequest\": {\"action\": \"play\"}}\n", + "Input: play a song\n", + "Output: {\"musicrequest\": {\"action\": \"play\"}}\n", + "Input: next song\n", + "Output: {\"musicrequest\": {\"action\": \"next\"}}\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "760baa5f-9368-4b5a-abc0-6ac65c34b7a7", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=None, artist=None, action=)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"stop the music now\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "593b106a-72e7-4c86-82a8-f9630a3bfabb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=['yellow submarine'], album=None, artist=['the beatles'], action=None)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"i want to hear yellow submarine by the beatles\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "8d728835-2e3e-40d3-8bba-2cd4bd4ec789", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=['goliath'], album=None, artist=['smith&thell'], action=None)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"play goliath by smith&thell\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "02c7f1e5-1c8d-4e9f-82e6-c37a41d6de14", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=['the lion king soundtrack'], artist=None, action=None)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"can you play the lion king soundtrack\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7a6d918c-53fe-426b-b37e-eec2abb8a704", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=None, artist=['paul simon', 'led zeppelin', 'the doors'], action=None)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"play songs by paul simon and led zeppelin and the doors\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "b18acf0a-d99e-48de-ace5-fb01bded5a41", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=None, artist=None, action=)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"could you play the previous song again?\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "8c5c06b5-7f3a-416d-a809-19004cb14750", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=None, artist=None, action=)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"previous\")[\"validated_data\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "03f33a42-e1c9-4bc2-a6b4-15d3f3c5ce32", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "MusicRequest(song=None, album=None, artist=None, action=)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"play the song before\")[\"validated_data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "95f22605-a2b0-401e-ac7d-48d97913d535", + "metadata": {}, + "source": [ + "## Validation in Action" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f779d4a2-ddb3-49c4-86cf-d9537b6ca6d4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Player(BaseModel):\n", + " song: List[str] = Field(\n", + " description=\"The song(s) that the user would like to be played.\"\n", + " ) # <-- Note this is NOT Optional\n", + " album: Optional[List[str]] = Field(\n", + " default=None, description=\"The album(s) that the user would like to be played.\"\n", + " )\n", + " artist: Optional[List[str]] = Field(\n", + " default=None,\n", + " description=\"The artist(s) whose music the user would like to hear.\",\n", + " examples=[(\"Songs by paul simon\", \"paul simon\")],\n", + " )\n", + " action: Optional[Action] = Field(\n", + " default=None,\n", + " description=\"The action that should be taken; one of `play`, `stop`, `next`, `previous`\",\n", + " examples=[\n", + " (\"Please stop the music\", \"stop\"),\n", + " (\"play something\", \"play\"),\n", + " (\"play a song\", \"play\"),\n", + " (\"next song\", \"next\"),\n", + " ],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "38979da3-13aa-4e34-b11c-3656d7e3b4f6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(Player)\n", + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"json\", validator=validator\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "ceaec432-480f-44f0-aad9-9eb8146f0f02", + "metadata": {}, + "source": [ + "Now the schema expects that a list of songs parsed out in the query." + ] + }, + { + "cell_type": "markdown", + "id": "229771c7-eb16-4a54-85ac-13f4f0d8c527", + "metadata": {}, + "source": [ + "### No valid data!\n", + "\n", + "We made *SONG* a required attribute in the pydantic schema above! Let's see what happens now!" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d594eb6e-02a0-4774-9dca-421db192372d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Error in LangChainTracer.on_chain_end callback: No constructor defined\n" + ] + }, + { + "data": { + "text/plain": [ + "{'data': {'player': {'action': 'stop'}},\n", + " 'raw': '{\"player\": {\"action\": \"stop\"}}',\n", + " 'errors': [1 validation error for Player\n", + " song\n", + " Field required [type=missing, input_value={'action': 'stop'}, input_type=dict]\n", + " For further information visit https://errors.pydantic.dev/2.3/v/missing],\n", + " 'validated_data': None}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"stop the music now\")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "672f9908-c6b7-47cf-8c82-03b0e5b8fa84", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Player(song=['yellow submarine'], album=None, artist=['the beatles'], action=None)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"i want to hear yellow submarine by the beatles\")[\"validated_data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "02559660-20a4-4fce-83a4-2e3b68794f19", + "metadata": {}, + "source": [ + "## Validating Collections\n", + "\n", + "Currently, there are a few gotchyas when modeling collections that depend on the encoder." + ] + }, + { + "cell_type": "markdown", + "id": "3da8c0fe-3765-4a6e-8925-85806e9500cc", + "metadata": {}, + "source": [ + "### CSV Encoder\n", + "\n", + "A CSV encoder is expected to work best when encoding a list of records.\n", + "\n", + "At the moment, the CSV encoder doesn't handle embedded lists or objects. \n", + "\n", + "(This works with either JSON or CSV.)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "cd9dffbe-82bf-4d1f-9b0a-3ec2c58b63d6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Person(BaseModel):\n", + " name: str = Field(description=\"The person's name\")\n", + " age: int = Field(description=\"The age of the person\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "f859b6e1-c2d8-48e0-af17-2ffb286bffe9", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(\n", + " Person,\n", + " description=\"Personal information\",\n", + " many=True,\n", + " examples=[(\"Joe is 10 years old\", {\"name\": \"Joe\", \"age\": \"10\"})],\n", + ")\n", + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"csv\", validator=validator\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "af6c6339-81db-482b-9507-31f41d2fa489", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "person: Array<{ // Personal information\n", + " name: string // The person's name\n", + " age: number // The age of the person\n", + "}>\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in CSV format in Excel dialect. Please use a | as the delimiter. \n", + " Do NOT add any clarifying information. Output MUST follow the schema above. Do NOT add any additional columns that do not appear in the schema.\n", + "\n", + "\n", + "\n", + "Input: Joe is 10 years old\n", + "Output: name|age\n", + "Joe|10\n", + "\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "837a08c2-8de0-448a-9984-0cf19a73d4a3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[Person(name='john', age=13), Person(name='maria', age=24)]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"john is 13 years old. maria is 24 years old\")[\"validated_data\"]" + ] + }, + { + "cell_type": "markdown", + "id": "7622135e-3a2e-41b2-a99f-980e5dd9f804", + "metadata": {}, + "source": [ + "## Complex Structure\n", + "\n", + "To serialize more complex structures, use the JSON encoder.\n", + "\n", + "So for the example, above the following alternative works:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "ee92ae5e-52e9-4405-9718-be71d25ce412", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Person(BaseModel):\n", + " name: str = Field(description=\"The person's name\")\n", + " age: int = Field(description=\"The age of the person\")\n", + "\n", + "\n", + "class Root(BaseModel):\n", + " people: List[Person] = Field(\n", + " description=\"Personal information\",\n", + " examples=[(\"John was 23 years old\", {\"name\": \"John\", \"age\": 23})],\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "b1c618c8-adab-48bd-bc5d-45dc5adb1dbb", + "metadata": {}, + "source": [ + "** NOTE ** Using a Root container and `many` = `False`" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "7464aab0-45fb-4e22-bed4-b695c7f60629", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(Root, description=\"Personal information\", many=False)\n", + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"json\", validator=validator\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "8becd13d-bd23-4d37-8fd3-7548a7fe51c1", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'data': {'root': {'people': [{'name': 'tom', 'age': 23},\n", + " {'name': 'Jessica', 'age': 75}]}},\n", + " 'raw': '{\"root\": {\"people\": [{\"name\": \"tom\", \"age\": 23}, {\"name\": \"Jessica\", \"age\": 75}]}}',\n", + " 'errors': [],\n", + " 'validated_data': Root(people=[Person(name='tom', age=23), Person(name='Jessica', age=75)])}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " \"My name is tom and i am 23 years old. Her name is Jessica and she is 75 years old.\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "7ea06fe0-104b-487a-ab78-cd23de66ec88", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "root: { // Personal information\n", + " people: Array<{ // Personal information\n", + " name: string // The person's name\n", + " age: number // The age of the person\n", + " }>\n", + "}\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in JSON format. Do not output anything except for the extracted information. Do not add any clarifying information. Do not add any fields that are not in the schema. If the text contains attributes that do not appear in the schema, please ignore them. All output must be in JSON format and follow the schema specified above. Wrap the JSON in tags.\n", + "\n", + "\n", + "\n", + "Input: John was 23 years old\n", + "Output: {\"root\": {\"people\": [{\"name\": \"John\", \"age\": 23}]}}\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "38245cd6-e188-40c9-a940-184da8755983", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Pet(BaseModel):\n", + " name: str = Field(description=\"the name of the pet\")\n", + " species: Optional[str] = Field(\n", + " default=None, description=\"The species of the pet; e.g., dog or cat\"\n", + " )\n", + " age: Optional[int] = Field(default=None, description=\"The number of the age; e.g.,\")\n", + " age_unit: Optional[str] = Field(\n", + " default=None, description=\"The unit of the age; e.g., days or weeks\"\n", + " )\n", + "\n", + "\n", + "class Person(BaseModel):\n", + " name: str = Field(description=\"The person's name\")\n", + " age: Optional[int] = Field(default=None, description=\"The age of the person\")\n", + " pets: List[Pet] = Field(\n", + " description=\"The pets owned by the person\",\n", + " examples=[\n", + " (\n", + " \"he had a dog by the name of charles that was 5 days old\",\n", + " {\"name\": \"dog\", \"species\": \"dog\", \"age\": \"5\", \"age_unit\": \"days\"},\n", + " )\n", + " ],\n", + " )\n", + "\n", + "\n", + "class Root(BaseModel):\n", + " people: List[Person] = Field(\n", + " description=\"Personal information\",\n", + " examples=[(\"John was 23 years old\", {\"name\": \"John\", \"age\": 23})],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "236a9510-6f69-4d63-8854-62e2c57380a6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "schema, validator = from_pydantic(\n", + " Root, description=\"Personal information for multiple people\", many=False\n", + ")\n", + "chain = create_extraction_chain(\n", + " llm, schema, encoder_or_encoder_class=\"json\", validator=validator\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "843e992a-32c5-4382-95ab-33eb3cd7810b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your goal is to extract structured information from the user's input that matches the form described below. When extracting information please make sure it matches the type information exactly. Do not add any attributes that do not appear in the schema shown below.\n", + "\n", + "```TypeScript\n", + "\n", + "root: { // Personal information for multiple people\n", + " people: Array<{ // Personal information\n", + " name: string // The person's name\n", + " age: number // The age of the person\n", + " pets: Array<{ // The pets owned by the person\n", + " name: string // the name of the pet\n", + " species: string // The species of the pet; e.g., dog or cat\n", + " age: number // The number of the age; e.g.,\n", + " age_unit: string // The unit of the age; e.g., days or weeks\n", + " }>\n", + " }>\n", + "}\n", + "```\n", + "\n", + "\n", + "Please output the extracted information in JSON format. Do not output anything except for the extracted information. Do not add any clarifying information. Do not add any fields that are not in the schema. If the text contains attributes that do not appear in the schema, please ignore them. All output must be in JSON format and follow the schema specified above. Wrap the JSON in tags.\n", + "\n", + "\n", + "\n", + "Input: John was 23 years old\n", + "Output: {\"root\": {\"people\": [{\"name\": \"John\", \"age\": 23}]}}\n", + "Input: he had a dog by the name of charles that was 5 days old\n", + "Output: {\"root\": {\"people\": [{\"pets\": [{\"name\": \"dog\", \"species\": \"dog\", \"age\": \"5\", \"age_unit\": \"days\"}]}]}}\n", + "Input: [user input]\n", + "Output:\n" + ] + } + ], + "source": [ + "print(chain.prompt.format_prompt(text=\"[user input]\").to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "e34b6194-9a2b-43a1-95c6-2c9930d036ed", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Root(people=[Person(name='Neo', age=None, pets=[Pet(name='Tom', species='dog', age=None, age_unit=None), Pet(name='Weeby', species='cat', age=23, age_unit='days')]), Person(name='Julia', age=None, pets=[Pet(name='Wind', species='horse', age=None, age_unit=None)])])" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\n", + " text=\"Neo had a dog by the name of Tom and a cat by the name of Weeby. Weeby was 23 days old. Julia owned a horse. The horses name was Wind\"\n", + ")[\"validated_data\"]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 0000000..d54be80 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,906 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + 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: 270px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +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: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +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 p.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%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +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; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +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; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +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; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption 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; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- 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; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.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-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +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 { + margin: 1em 0; +} + +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; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/check-solid.svg b/_static/check-solid.svg new file mode 100644 index 0000000..92fad4b --- /dev/null +++ b/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/clipboard.min.js b/_static/clipboard.min.js new file mode 100644 index 0000000..54b3c46 --- /dev/null +++ b/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/_static/copybutton.css b/_static/copybutton.css new file mode 100644 index 0000000..f1916ec --- /dev/null +++ b/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/_static/copybutton.js b/_static/copybutton.js new file mode 100644 index 0000000..2ea7ff3 --- /dev/null +++ b/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js new file mode 100644 index 0000000..dbe1aaa --- /dev/null +++ b/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/_static/css/custom.css b/_static/css/custom.css new file mode 100644 index 0000000..673008a --- /dev/null +++ b/_static/css/custom.css @@ -0,0 +1,13 @@ +pre { + white-space: break-spaces; +} + +@media (min-width: 1200px) { + .container, + .container-lg, + .container-md, + .container-sm, + .container-xl { + max-width: 2560px !important; + } +} diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 0000000..e1bfd70 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,358 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + this.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + var url = new URL(window.location); + url.searchParams.delete('highlight'); + window.history.replaceState({}, '', url); + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar : function() { + $('input[name=q]').first().focus(); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + return; + + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON') { + if (event.altKey || event.ctrlKey || event.metaKey) + return; + + if (!event.shiftKey) { + switch (event.key) { + case 'ArrowLeft': + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) + break; + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 'ArrowRight': + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) + break; + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + case 'Escape': + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + break; + Documentation.hideSearchWords(); + return false; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case '/': + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + break; + Documentation.focusSearchBar(); + return false; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 0000000..f618920 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '1.0.1', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: true, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/_static/images/logo_binder.svg b/_static/images/logo_binder.svg new file mode 100644 index 0000000..45fecf7 --- /dev/null +++ b/_static/images/logo_binder.svg @@ -0,0 +1,19 @@ + + + + +logo + + + + + + + + diff --git a/_static/images/logo_colab.png b/_static/images/logo_colab.png new file mode 100644 index 0000000000000000000000000000000000000000..b7560ec216b2d1b6f77855525fe966c741833428 GIT binary patch literal 7601 zcmeI1^;ZuSFsz@@e&Hu|o~yU_Jn_7Cy4b4(M?f2S`owL6D#ysoM3Rsb4MX|l6hl52QIsX*kmQMmFZ6Xu|Wk1r15+E^+Er?@^MFpIE zq!=C|$Nn*F4aR@N|DPxS6E^f|7Z=H%T>vS)_|-RkkprWw zSGb9TlwheKfo{U5J)kX1$cHtEFe}Pa2Au|?^hCk%8gdI}l*ypIUsLXLMy9W|q-ZAw zJpZkmGRa|!=7CyrA#Bs2?5UdZ1^pDaji}+DimdE$JB@FrJvAIxy*3v#1-8OwO;OS$ zsv*P<%V4%?*Keca@o9}LMOs~ph)z!AU;${{23k&Gq7A@nDP{*I1HiTZ=Q*54?Bok) zp6L_4HhiE->YU6{m*{7O7j#SkBb9JPo!k8TD0H6{ zdSE-mmA!Js{}(?qh${0wB7Rx{*F=43D>?j3kU8MX&`sQJ+wHUD6eEr7j%*2x%5|a8 z*;AP<*tCQwj`Af5vvGHXF=9{cdzV2BMI@}VHgmol)^f>Ectcls5p3dW?40~ADd>ki za*q>v=nQQmGI5&BS!GU|iX9>qB9r=_Qm9t_Qwi+zWI zc%%oQ`P}{ZXk^}?+H!u2my^C#TD%=V|3pb$MXhJ07bx-^=oxj?ZSk!---?f2cs8_& z8?O{lvxMDZi7gsdvoZ2bmyLYs1!O1RMC)1Wv`9p-I(1pfww9siX;Lu>^>_Y=g+OHo zPm(N|h?h5Z>yze~wKtPBRv(mZx*A4R%bganw#OV=SE*=J^b#~(YfIcj(k=(i37PY7 zUiawSj8SKczPk-^=SwOOb%X+bRcFm+=N1r{{CA<=kbVq8cFGcLSGqM5FUxChbc&`o9$mUo4kZLh+%KP6m zDMd3SH~N5fH8J+8;bpxhi-9i}^PV(^u?zb49_c!Ow_!1w%w(RLEeXJoMU>Nnlc8sd z<;K$L<-WwC`NJ0PWzB59Pzbg|FZS-=xlaWDjM-PXIJ;r4qyFnFc_<-VDg5P=Zk0Pd z%f7GFg?FzC??rmjG^Ib<{cfE+dud-%)Ep=a8Q(Z-Fng}&CvD+JPdO)mL-$u4eH#LJ z7heze_GA*{rYAL;ejb#P;oTD_*Rgrw;)1(e;+zGN{)D)k?o$t&BGWEM!Hn}LQm1jd zf@B0+pEzI&qREI@Qr=#K;u~Fs)Saf>_1X|EQGz0D_a|>)d?IOck($^4a`v4Hc6sKV zgm7-VK|sz+(A$-L0BnhZ#qKk${svcv4#QmCcMCb>t9=e+^b49rrK@5C@-Qs{PN6H8Tb^nIy#)VA`)o~+c~m2m9bN}EcwI`-IP+fB&d^;19iX9{XvM6VYHE(fX{BIU zjMLmkl7p}TslG;@C!HvX=7hVy6cGIM{h7hxrM^q{j`Y4Ux1nI*k9MB?ToSK!Qpvy< zT~`Qofe|OBk8vza_r02Y;~+V6WKn(J{_?BR9@-`D&Q;nTEx7+j36Qk0(l3TahUki} z;O-FUuOnNVcc-Q3c?;A)ZpgKC-Sa8`{c}MNm$j))KPPdL#xR*0kxQz|V-;WZxI+?u zFB#~P=os0);b?+6$-z@yE%k*^!0x)K_!|4!L%ADpXqe`pG|8A+rht_!jZid=wb1j& zjPG_SeS*{ef!h*}~k!*;Aar3`tCeHO@>c{c>ak(x3f^w3+_zT>j)aP_hVoV4~^0L<5^eu_y z-@tf0YyH-(#5uTh`s3DIhpc^`UysO{L8JS|z=qnHFb)UqfMnC!Hu$=eiC+a;9t*X6R?Q8POFRq?_ak1&yP&YF6`@B=qySm8MJ)n*E zdS-&E$a$DMp!}+S%^(Q))m7O$Qece1ZtB+=H{**c0@XT53VGNeFhvnDVocubi6~ru z2X&(|kp)joFLfuG?i;d=&CZBQhez8i+lhV+c;_pEL6+Teo z1qclCF-EO~XWkH3u|unGI79@`+YLi}rF>PbBrn{PBKWF&S%K6N0u^DRx7qImnJ`+c z>Nu)TJyhpyJX_!XHh^82M+YgW&cxs(vQKEpL%}iK(hH=<@)j#E3_?a*JP@0=R z;O*(_2@>IjYLClnL+$PJ-5!vt6>UJ7$KHM3LlFFMxb19oFZ_fi@{fp};$@_n8driG z`=77&{Z^0#T>t%$hCqQi8M}0E4XipxikcsB$>o9M)rBJWQDY7UrgKAy|BP4kr`Nay z??T|Ajh_U=3lem-tL$_tEhB=Rqfi?bUj`u>$a-x5WxqHn6t4)Q-NQ^Bt-k!mcE0ES z4)*3-(5@V)=EloLT~ReorH252&Q&MWWc$oiSS{!xpO?VPpJFD-QN6c=<7HxnH1nH% zeiOM22U=%trq`HCXYNL#H!P!M1{?)QcIGYWO$;mCMHnpgd?*ZE&bmylPxndZ$B}ct zIfSCaCu!a^rBwLoo4gQJnU<%~!6cPP-qxJLZM#F&_gwU%?O$k?DIF6l%q_lvcs3})|Z?z(K3q9(BASQtZlw@+<5mv zrHuRbc}A4I9hLtxbS!@ju49VVt1XxpO?1&$LA;?ZANYo=SC^nMg{9BY`=cZcTaR{A@r{UB@;%H zPb6QWRuvU)J>>*0FB;9Uq|hH4C$u8T=T?sz{5%Ex)I%5W6wQmtel=rJ)Tbw#E7{Z;t3U zY9a$t=WkneF<9867^HBvLp>hs;A@H}9KEwn2t!?ITQ1vZ?fCFF(RfFYplQUymF`y4 z74MX)v7%4i_52G~fn=&qCfo}f%Gj8bd7dI^BDI?AlVN_!qWMJT#NBLs^p)e{tG?D4 z)|x9tIcLpO$-JtVj=#$1Y&GRE*-xUKd_{uxiZkqAudNRF!dph|+p41KtIf(8)c1p~ zv)f(_RGUK*j_{s!DNDET-@ekFNlnTXW_=+4t5>Qbq`aWl%F6e}e)<=0U{Lp}8twQ? z8cJ&^2hntuxcqQ~k;<29cTQz)@X@zbQN?f1q??MK&`gi2me&l@XLSxN|!? z;kRJcy-ahz{?{Aj;b0E9*MKf|Q@H!%2FhB8=t$dhTtR4^%hSctIRz;tXJPme_gd zLiJlhH^x9|I?_vaIKkgiAyrk&%Mv26OqK|av#t%u9aU2`wvZ61wo4$DW%z~d9P`5& zx2Zk{zL$Z1@bGicZ})KZzJKhZaZ+P!-p1uH9dgwUQ5u(q{HyTaprSe95WuIadBYv0 zPUJ~G+G2~n0DfE{7!{N*#1+?ql4nK8`Fr?o@j~3c(>T^^trK4t~7#7WQoVk)7KnFY{iPIQ?Qh8 z+Wy6Ol|m6pA8r4lQdt@$=Z{k}^_evzh~Vt_J$aBM!djok7rTfxt8f+KVv7GM1Awc>b%$6NDX zcl~`@-PYtGJSGIO(C^sr&BxXHz*cUJnB~X1`0$kX)@xH+qFRp1^Vpt^u3V$(w;_vf zHIi3Mb+A5@Nx^>r8g^tF%=j0o$Rhli22c4xiy2SEGE=Dk)m)mzF}VhHtiP43?%dTPKbDg+Gmq$pq6DlCZzY5@`})4DTSfgVh3B z6B#;izoI9B%{^V1qYVp<-KgZ=_(;UqyU^wT{IFPQ?YY4%;yq4cbgN`_dqp${t%ytU z!T>q+J?*26u4Ak4Jx#9uHgScR2!%5YX9%5Bu@HL^VaJ7%jj#ceYuaRZk7vMWX)jq| z-rX)3v33MqZ$qaWp!X$i1yJ*rOfjP-u6noa{n9pxzJw0P2+@UNLHS(-e>##A#9xc` zAr=;dh7~9d71L_&bj`DI@l$2 zSX@4j7tZbUYdo?rgctpAg3>Z@gv1{~grCRQUGVyTbzIJ-YZt2xF(cT)W0~l-76Lw* z<6YF%D4R$X>ZEj#!c)zMi018e@?^1%&N`zutD(OQ;X8am+pNW(YhRwy*%wrsnwb#T z>n{K;55wQE!cVF)X+X12fX<x`lE~DquFsMPRoBuzhuVdR8Gv zevya06i9>q3oJZyDGUHOP=iTbBg`AO7~BI0N8$lqEvK_=V)(Du!8=i|%_2^xqnCgh zYEho!c`8!%;N8>VD_@8NZxuyDHBlxl_=CBT5z4cft(NLsv9Wo81)VnjTne@sFAuLA zv^?3h>Rc?eDzkn@SvwCF^spU#ZJuQz6o4V90>Al2JL^>6N4y0wyg#4m?khQ$4$xa5 zlJZV5E$o~arUalDb_b7lXJs*(UA*P>jQ%3i`I8pyKN?*kY>iRE7J9GGiz^nA>aIV> zaJ}>Ecj_*#d8xFcjhy+6oRGfCr^qR6C2fGkhPUT-of7St?XBEaY>?_o$Y;IiV*<6d zlA;M(1^;P>tJxjiTQAB{T$TKPJ?7HfGON=ms6=%yai0?j-qHB-nhvKj_0=^YawDhO z&$wC;93X#RhmcNJTfn66z&E;UAFGeV6TsD61;r(%GZvUrDg2W3Y2hPsTqkinoI4PV zXDedcq+P^|`+Zqpt5*;9cKbAf6!xI4X{#P5OMaE4?*}B?BIY^Gyv0%UUq}lKO~C#Z zCRamrC=OeXKTKm|4p>}U!kLbE%NxPGuZ1-DR(wWFK@>24ca*qhEt5B*r|(Kty!Pj0 zZauh;NqoiV&&q9pT#S7@dl4JUVA|RmaH8kslFhypJ_)20*ebs^yXIQA(6mi|Wph<8 z=`?$6$QX%TaWE9DLjOgi>rciE+f(9`A4gn4&jZA)v29ug%2=CtvV-U|71pd@edT~> zTA~BLBxs`RYEh%@DuEBdVt=S~6x5VXGkg4=c(|;e@Uk2Mxd}~#h^+`jF}r@=C0+HS zJcg`@*AUj2Ymhzqb=;b}w_oSQ>VH<@k=B`!P>>u5;cpo7O#PB&IQ>AS{06fz5fsXyOt1R0^~JUdht$M7yYTxq$&$T&teFpg;y{BUxXR(00s6bHa2EU zQz~u3(zn7I;Ei{D%kc60jYvUAK^2vZcMr$(Mvo58z}?>{fBdZv&KdKaM(W*WeijQ+ z;}+j>_K=@gAG4KLl-oHs1uHl{4Iq_bV|(|n23Ml=$x+vE+w;rZ1-;Cgwa-{hvjGND zf$}y#wu81ZOPZ@Wj}WbIj4k%PEPTy)sLP0Kk0C=n2lpOrPl~et;FC1`zjD=4!5coL zUgdZMo&inr`+cr#<^beEmG){%LjzXvEJ;=`hMnEYG|VU#W^gR^?uh;u@MsY$78=09EY#xn`@9X5)nb~&t)6wi zB(Y#$oL!o_oI|#`LeD5m>ezV6;nKHq@ZYvUufb~M33Qw%6`GhEa}S@P!}T;dH@bLx zG_yiKDTq6zQz}25>oeWOXpL<9!kJrP)LQASx)Dh$MiaKmk}q7TZJjtiA`M6zv_)Sn zoW-S@(c2ebP+DQqvD-S;#gt=zlveyhax!aybe(eZtlKEO1+bZSM diff --git a/_static/images/logo_jupyterhub.svg b/_static/images/logo_jupyterhub.svg new file mode 100644 index 0000000..60cfe9f --- /dev/null +++ b/_static/images/logo_jupyterhub.svg @@ -0,0 +1 @@ +logo_jupyterhubHub diff --git a/_static/jquery-3.5.1.js b/_static/jquery-3.5.1.js new file mode 100644 index 0000000..5093733 --- /dev/null +++ b/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( 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 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. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// 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 arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( 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" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // 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 ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = 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" && !isFunction( target ) ) { + target = {}; + } + + // 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 ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // 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; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + 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; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // 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 Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // 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 = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // 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 = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + 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 = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // 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 + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "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 + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + 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)|^-$|[^\0-\x1f\x7f-\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(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + 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 { + + // 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; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // 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 ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @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 + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === 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: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + 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 ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // 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( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // 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 programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + 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 + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // 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 https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // 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 + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // 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 + // 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 ( !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( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // 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 ( !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( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + 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 ( 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" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...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 ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + 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; + } + + // 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; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + 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(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // 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 ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // 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 + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + 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++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `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++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // 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 ) { + + // 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" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +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( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// 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; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + 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 ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + 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[ 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 ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // 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 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // 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 ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // 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.uniqueSort( matched ) : matched ); + }, + + // 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; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // 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() { + + // Enforce single-firing + locked = 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; + + // 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 { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // 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 ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + 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.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : 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; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // 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.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // 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 = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "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 ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = 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 && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).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 ( 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, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + 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 ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // 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" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // 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.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 ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // 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 ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + 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 = jQuery.Deferred(); + +jQuery.fn.ready = function( 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( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// 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 ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// 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; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +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 Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // 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 ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // 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 + } ); + } + } + } + + 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" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // 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 ) ) { + + return this.get( owner, key ); + } + + // 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 ); + + // 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 ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // 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(); + +var dataUser = new Data(); + + + +// 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 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // 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 ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // 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 dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + 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; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // 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() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + 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( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + 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 ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || 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. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + 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 = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + 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; +} + + +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; + } + + display = elem.style.display; + if ( show ) { + + // 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"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // 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 ]; + } + } + + 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 ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( 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 = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// 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" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, 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 ( toType( 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 = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +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. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + 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 ) ) { + events = elemData.events = Object.create( null ); + } + 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 !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + 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 ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + 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; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + 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 ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // 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 ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native 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 + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + 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 ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + 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 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + 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 + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, 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 ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // 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; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// 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 && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// 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, + code: 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 ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// 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", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // 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 ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + 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.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // 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; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // 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; + + // 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 ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + 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 && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + 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 ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // 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 ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + 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 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 domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + 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 ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // 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 rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // 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; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + 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.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // 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; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // 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"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, 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.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // 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 ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( 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 emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // 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]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // 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[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +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; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // 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; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // 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 "+=" 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 (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // 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 ( isCustomProp ) { + style.setProperty( name, value ); + } else { + 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 ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // 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 + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // 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, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + 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( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // 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. + // 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 available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// 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 ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + 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 +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // 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 ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + 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 && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + 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(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // 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 ); + } + } + + // 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 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // 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" ); + } + 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 ] ); + } + } + + // 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"; + } + } + } + + 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 ] ); + } + } ); + } + + // 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; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ 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 ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // 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 ), + + // 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++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // 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++ ) { + animation.tweens[ index ].run( 1 ); + } + + // 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 = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +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 ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // 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: 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 || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + 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. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + 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 + data.finish = true; + + // 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 + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // 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 + delete data.finish; + } ); + } +} ); + +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" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// 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 = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // 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 === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // 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" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// 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 { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // 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)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + 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 ) { + + // 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" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// 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 +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } 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`, + // 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. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + 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; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + 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 ( Array.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 + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = 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 || + !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 ( Array.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; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = 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 && !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() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ 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 && isFunction( elem[ type ] ) && !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; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + 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 ); + } + } +} ); + + +// 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 ) { + + // 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 ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + 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 ( Array.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 && toType( 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 = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.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(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // 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 ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +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(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + 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: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + 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" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // 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, + + // 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, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + 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 ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // 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 || 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 = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // 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 + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // 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" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // 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 and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // 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. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // 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.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + 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 + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + 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 = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + 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 + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // 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 ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + 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, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // 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 + ); + + // 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 ); + } + + // 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"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + 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( + + // 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 = xhr.ontimeout = callback( "error" ); + + // 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(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + 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 ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// 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( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// 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"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " +{% endmacro %} diff --git a/_static/scripts/pydata-sphinx-theme.js b/_static/scripts/pydata-sphinx-theme.js new file mode 100644 index 0000000..0e00c4c --- /dev/null +++ b/_static/scripts/pydata-sphinx-theme.js @@ -0,0 +1,32 @@ +!function(t){var e={};function n(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return t[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(i,o,function(e){return t[e]}.bind(null,o));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=2)}([function(t,e){t.exports=jQuery},function(t,e,n){"use strict";n.r(e),function(t){ +/**! + * @fileOverview Kickass library to create and place poppers near their reference elements. + * @version 1.16.1 + * @license + * Copyright (c) 2016 Federico Zivolo and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +var n="undefined"!=typeof window&&"undefined"!=typeof document&&"undefined"!=typeof navigator,i=function(){for(var t=["Edge","Trident","Firefox"],e=0;e=0)return 1;return 0}();var o=n&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),i))}};function r(t){return t&&"[object Function]"==={}.toString.call(t)}function a(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function s(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function l(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=a(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/(auto|scroll|overlay)/.test(n+o+i)?t:l(s(t))}function u(t){return t&&t.referenceNode?t.referenceNode:t}var f=n&&!(!window.MSInputMethodContext||!document.documentMode),d=n&&/MSIE 10/.test(navigator.userAgent);function c(t){return 11===t?f:10===t?d:f||d}function h(t){if(!t)return document.documentElement;for(var e=c(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===a(n,"position")?h(n):n:t?t.ownerDocument.documentElement:document.documentElement}function p(t){return null!==t.parentNode?p(t.parentNode):t}function m(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?t:e,o=n?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var a,s,l=r.commonAncestorContainer;if(t!==l&&e!==l||i.contains(o))return"BODY"===(s=(a=l).nodeName)||"HTML"!==s&&h(a.firstElementChild)!==a?h(l):l;var u=p(t);return u.host?m(u.host,e):m(t,p(e).host)}function g(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",i=t.nodeName;if("BODY"===i||"HTML"===i){var o=t.ownerDocument.documentElement,r=t.ownerDocument.scrollingElement||o;return r[n]}return t[n]}function v(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=g(e,"top"),o=g(e,"left"),r=n?-1:1;return t.top+=i*r,t.bottom+=i*r,t.left+=o*r,t.right+=o*r,t}function _(t,e){var n="x"===e?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+i+"Width"])}function b(t,e,n,i){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],c(10)?parseInt(n["offset"+t])+parseInt(i["margin"+("Height"===t?"Top":"Left")])+parseInt(i["margin"+("Height"===t?"Bottom":"Right")]):0)}function y(t){var e=t.body,n=t.documentElement,i=c(10)&&getComputedStyle(n);return{height:b("Height",e,n,i),width:b("Width",e,n,i)}}var w=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},E=function(){function t(t,e){for(var n=0;n2&&void 0!==arguments[2]&&arguments[2],i=c(10),o="HTML"===e.nodeName,r=N(t),s=N(e),u=l(t),f=a(e),d=parseFloat(f.borderTopWidth),h=parseFloat(f.borderLeftWidth);n&&o&&(s.top=Math.max(s.top,0),s.left=Math.max(s.left,0));var p=S({top:r.top-s.top-d,left:r.left-s.left-h,width:r.width,height:r.height});if(p.marginTop=0,p.marginLeft=0,!i&&o){var m=parseFloat(f.marginTop),g=parseFloat(f.marginLeft);p.top-=d-m,p.bottom-=d-m,p.left-=h-g,p.right-=h-g,p.marginTop=m,p.marginLeft=g}return(i&&!n?e.contains(u):e===u&&"BODY"!==u.nodeName)&&(p=v(p,e)),p}function k(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,i=D(t,n),o=Math.max(n.clientWidth,window.innerWidth||0),r=Math.max(n.clientHeight,window.innerHeight||0),a=e?0:g(n),s=e?0:g(n,"left"),l={top:a-i.top+i.marginTop,left:s-i.left+i.marginLeft,width:o,height:r};return S(l)}function A(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===a(t,"position"))return!0;var n=s(t);return!!n&&A(n)}function I(t){if(!t||!t.parentElement||c())return document.documentElement;for(var e=t.parentElement;e&&"none"===a(e,"transform");)e=e.parentElement;return e||document.documentElement}function O(t,e,n,i){var o=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r={top:0,left:0},a=o?I(t):m(t,u(e));if("viewport"===i)r=k(a,o);else{var f=void 0;"scrollParent"===i?"BODY"===(f=l(s(e))).nodeName&&(f=t.ownerDocument.documentElement):f="window"===i?t.ownerDocument.documentElement:i;var d=D(f,a,o);if("HTML"!==f.nodeName||A(a))r=d;else{var c=y(t.ownerDocument),h=c.height,p=c.width;r.top+=d.top-d.marginTop,r.bottom=h+d.top,r.left+=d.left-d.marginLeft,r.right=p+d.left}}var g="number"==typeof(n=n||0);return r.left+=g?n:n.left||0,r.top+=g?n:n.top||0,r.right-=g?n:n.right||0,r.bottom-=g?n:n.bottom||0,r}function x(t){return t.width*t.height}function j(t,e,n,i,o){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var a=O(n,i,r,o),s={top:{width:a.width,height:e.top-a.top},right:{width:a.right-e.right,height:a.height},bottom:{width:a.width,height:a.bottom-e.bottom},left:{width:e.left-a.left,height:a.height}},l=Object.keys(s).map((function(t){return C({key:t},s[t],{area:x(s[t])})})).sort((function(t,e){return e.area-t.area})),u=l.filter((function(t){var e=t.width,i=t.height;return e>=n.clientWidth&&i>=n.clientHeight})),f=u.length>0?u[0].key:l[0].key,d=t.split("-")[1];return f+(d?"-"+d:"")}function L(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=i?I(e):m(e,u(n));return D(n,o,i)}function P(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),i=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+i,height:t.offsetHeight+n}}function F(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function R(t,e,n){n=n.split("-")[0];var i=P(t),o={width:i.width,height:i.height},r=-1!==["right","left"].indexOf(n),a=r?"top":"left",s=r?"left":"top",l=r?"height":"width",u=r?"width":"height";return o[a]=e[a]+e[l]/2-i[l]/2,o[s]=n===s?e[s]-i[u]:e[F(s)],o}function M(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function B(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t[e]===n}));var i=M(t,(function(t){return t[e]===n}));return t.indexOf(i)}(t,"name",n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&r(n)&&(e.offsets.popper=S(e.offsets.popper),e.offsets.reference=S(e.offsets.reference),e=n(e,t))})),e}function H(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=L(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=j(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=R(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=B(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function q(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function Q(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),i=0;i1&&void 0!==arguments[1]&&arguments[1],n=Z.indexOf(t),i=Z.slice(n+1).concat(Z.slice(0,n));return e?i.reverse():i}var et="flip",nt="clockwise",it="counterclockwise";function ot(t,e,n,i){var o=[0,0],r=-1!==["right","left"].indexOf(i),a=t.split(/(\+|\-)/).map((function(t){return t.trim()})),s=a.indexOf(M(a,(function(t){return-1!==t.search(/,|\s/)})));a[s]&&-1===a[s].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,u=-1!==s?[a.slice(0,s).concat([a[s].split(l)[0]]),[a[s].split(l)[1]].concat(a.slice(s+1))]:[a];return(u=u.map((function(t,i){var o=(1===i?!r:r)?"height":"width",a=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,a=!0,t):a?(t[t.length-1]+=e,a=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,i){var o=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+o[1],a=o[2];if(!r)return t;if(0===a.indexOf("%")){var s=void 0;switch(a){case"%p":s=n;break;case"%":case"%r":default:s=i}return S(s)[e]/100*r}if("vh"===a||"vw"===a){return("vh"===a?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r}return r}(t,o,e,n)}))}))).forEach((function(t,e){t.forEach((function(n,i){K(n)&&(o[e]+=n*("-"===t[i-1]?-1:1))}))})),o}var rt={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],i=e.split("-")[1];if(i){var o=t.offsets,r=o.reference,a=o.popper,s=-1!==["bottom","top"].indexOf(n),l=s?"left":"top",u=s?"width":"height",f={start:T({},l,r[l]),end:T({},l,r[l]+r[u]-a[u])};t.offsets.popper=C({},a,f[i])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n=e.offset,i=t.placement,o=t.offsets,r=o.popper,a=o.reference,s=i.split("-")[0],l=void 0;return l=K(+n)?[+n,0]:ot(n,r,a,s),"left"===s?(r.top+=l[0],r.left-=l[1]):"right"===s?(r.top+=l[0],r.left+=l[1]):"top"===s?(r.left+=l[0],r.top-=l[1]):"bottom"===s&&(r.left+=l[0],r.top+=l[1]),t.popper=r,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||h(t.instance.popper);t.instance.reference===n&&(n=h(n));var i=Q("transform"),o=t.instance.popper.style,r=o.top,a=o.left,s=o[i];o.top="",o.left="",o[i]="";var l=O(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);o.top=r,o.left=a,o[i]=s,e.boundaries=l;var u=e.priority,f=t.offsets.popper,d={primary:function(t){var n=f[t];return f[t]l[t]&&!e.escapeWithReference&&(i=Math.min(f[n],l[t]-("right"===t?f.width:f.height))),T({},n,i)}};return u.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";f=C({},f,d[e](t))})),t.offsets.popper=f,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,i=e.reference,o=t.placement.split("-")[0],r=Math.floor,a=-1!==["top","bottom"].indexOf(o),s=a?"right":"bottom",l=a?"left":"top",u=a?"width":"height";return n[s]r(i[s])&&(t.offsets.popper[l]=r(i[s])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!G(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var o=t.placement.split("-")[0],r=t.offsets,s=r.popper,l=r.reference,u=-1!==["left","right"].indexOf(o),f=u?"height":"width",d=u?"Top":"Left",c=d.toLowerCase(),h=u?"left":"top",p=u?"bottom":"right",m=P(i)[f];l[p]-ms[p]&&(t.offsets.popper[c]+=l[c]+m-s[p]),t.offsets.popper=S(t.offsets.popper);var g=l[c]+l[f]/2-m/2,v=a(t.instance.popper),_=parseFloat(v["margin"+d]),b=parseFloat(v["border"+d+"Width"]),y=g-t.offsets.popper[c]-_-b;return y=Math.max(Math.min(s[f]-m,y),0),t.arrowElement=i,t.offsets.arrow=(T(n={},c,Math.round(y)),T(n,h,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(q(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=O(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split("-")[0],o=F(i),r=t.placement.split("-")[1]||"",a=[];switch(e.behavior){case et:a=[i,o];break;case nt:a=tt(i);break;case it:a=tt(i,!0);break;default:a=e.behavior}return a.forEach((function(s,l){if(i!==s||a.length===l+1)return t;i=t.placement.split("-")[0],o=F(i);var u=t.offsets.popper,f=t.offsets.reference,d=Math.floor,c="left"===i&&d(u.right)>d(f.left)||"right"===i&&d(u.left)d(f.top)||"bottom"===i&&d(u.top)d(n.right),m=d(u.top)d(n.bottom),v="left"===i&&h||"right"===i&&p||"top"===i&&m||"bottom"===i&&g,_=-1!==["top","bottom"].indexOf(i),b=!!e.flipVariations&&(_&&"start"===r&&h||_&&"end"===r&&p||!_&&"start"===r&&m||!_&&"end"===r&&g),y=!!e.flipVariationsByContent&&(_&&"start"===r&&p||_&&"end"===r&&h||!_&&"start"===r&&g||!_&&"end"===r&&m),w=b||y;(c||v||w)&&(t.flipped=!0,(c||v)&&(i=a[l+1]),w&&(r=function(t){return"end"===t?"start":"start"===t?"end":t}(r)),t.placement=i+(r?"-"+r:""),t.offsets.popper=C({},t.offsets.popper,R(t.instance.popper,t.offsets.reference,t.placement)),t=B(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],i=t.offsets,o=i.popper,r=i.reference,a=-1!==["left","right"].indexOf(n),s=-1===["top","left"].indexOf(n);return o[a?"left":"top"]=r[n]-(s?o[a?"width":"height"]:0),t.placement=F(e),t.offsets.popper=S(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!G(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=M(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottomn.right||e.top>n.bottom||e.right2&&void 0!==arguments[2]?arguments[2]:{};w(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=o(this.update.bind(this)),this.options=C({},t.Defaults,a),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(C({},t.Defaults.modifiers,a.modifiers)).forEach((function(e){i.options.modifiers[e]=C({},t.Defaults.modifiers[e]||{},a.modifiers?a.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return C({name:t},i.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&r(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)})),this.update();var s=this.options.eventsEnabled;s&&this.enableEventListeners(),this.state.eventsEnabled=s}return E(t,[{key:"update",value:function(){return H.call(this)}},{key:"destroy",value:function(){return W.call(this)}},{key:"enableEventListeners",value:function(){return Y.call(this)}},{key:"disableEventListeners",value:function(){return z.call(this)}}]),t}();at.Utils=("undefined"!=typeof window?window:t).PopperUtils,at.placements=J,at.Defaults=rt,e.default=at}.call(this,n(4))},function(t,e,n){t.exports=n(5)},function(t,e,n){ +/*! + * Bootstrap v4.6.1 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),r=i(n);function a(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=f,o.default.event.special[d.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c=o.default.fn.alert,h=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,"bs.alert"),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.alert");i||(i=new t(this),n.data("bs.alert",i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',h._handleDismiss(new h)),o.default.fn.alert=h._jQueryInterface,o.default.fn.alert.Constructor=h,o.default.fn.alert.noConflict=function(){return o.default.fn.alert=c,h._jQueryInterface};var p=o.default.fn.button,m=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector('input:not([type="hidden"])');if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains("active"))t=!1;else{var r=n.querySelector(".active");r&&o.default(r).removeClass("active")}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains("active")),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&o.default(this._element).toggleClass("active"))},e.dispose=function(){o.default.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),r=i.data("bs.button");r||(r=new t(this),i.data("bs.button",r)),r.shouldAvoidTriggerChange=n,"toggle"===e&&r[e]()}))},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(".btn")[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector('input:not([type="hidden"])');if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||m._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var e=o.default(t.target).closest(".btn")[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide("next")},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide("prev")},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(".active.carousel-item");var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one("slid.bs.carousel",(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?"next":"prev";this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(v),o.default.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=l({},b,t),d.typeCheckConfig(g,t,y),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&w[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&w[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var a=(o+("prev"===t?-1:1))%this._items.length;return-1===a?this._items[this._items.length-1]:this._items[a]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(".active.carousel-item")),r=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(r),r},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass("active");var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass("active")}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(".active.carousel-item");if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,i,r,a=this,s=this._element.querySelector(".active.carousel-item"),l=this._getItemIndex(s),u=e||s&&this._getItemByDirection(t,s),f=this._getItemIndex(u),c=Boolean(this._interval);if("next"===t?(n="carousel-item-left",i="carousel-item-next",r="left"):(n="carousel-item-right",i="carousel-item-prev",r="right"),u&&o.default(u).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(u,r).isDefaultPrevented()&&s&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u),this._activeElement=u;var h=o.default.Event("slid.bs.carousel",{relatedTarget:u,direction:r,from:l,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(s).addClass(n),o.default(u).addClass(n);var p=d.getTransitionDurationFromElement(s);o.default(s).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass("active"),o.default(s).removeClass("active "+i+" "+n),a._isSliding=!1,setTimeout((function(){return o.default(a._element).trigger(h)}),0)})).emulateTransitionEnd(p)}else o.default(s).removeClass("active"),o.default(u).addClass("active"),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data("bs.carousel"),i=l({},b,o.default(this).data());"object"==typeof e&&(i=l({},i,e));var r="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data("bs.carousel",n)),"number"==typeof e)n.to(e);else if("string"==typeof r){if(void 0===n[r])throw new TypeError('No method named "'+r+'"');n[r]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var r=l({},o.default(i).data(),o.default(this).data()),a=this.getAttribute("data-slide-to");a&&(r.interval=!1),t._jQueryInterface.call(o.default(i),r),a&&o.default(i).data("bs.carousel").to(a),e.preventDefault()}}},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return b}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",E._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=a,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass("show")?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!(this._isTransitioning||o.default(this._element).hasClass("show")||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains("collapse")}))).length&&(e=null),e&&(n=o.default(e).not(this._selector).data("bs.collapse"))&&n._isTransitioning))){var r=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(r),!r.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data("bs.collapse",null));var a=this._getDimension();o.default(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[a]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var s="scroll"+(a[0].toUpperCase()+a.slice(1)),l=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass("collapsing").addClass("collapse show"),i._element.style[a]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(l),this._element.style[a]=this._element[s]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass("show")){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass("collapsing").removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var r=0;r0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=l({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),l({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data("bs.dropdown");if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data("bs.dropdown",n)),"string"==typeof e){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),i=0,r=n.length;i0&&a--,40===e.which&&adocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove("modal-static"),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass("fade"),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var r=o.default.Event("shown.bs.modal",{relatedTarget:t}),a=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(r)};if(n){var s=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()},e._enforceFocus=function(){var t=this;o.default(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off("keydown.dismiss.bs.modal")},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):o.default(window).off("resize.bs.modal")},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger("hidden.bs.modal")}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on("click.dismiss.bs.modal",(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass("show"),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass("show");var r=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass("fade")){var a=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,r).emulateTransitionEnd(a)}else r()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:B,popperConfig:null},X={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},$={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},G=function(){function t(t,e){if(void 0===r.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var a=this.getTipElement(),s=d.getUID(this.constructor.NAME);a.setAttribute("id",s),this.element.setAttribute("aria-describedby",s),this.setContent(),this.config.animation&&o.default(a).addClass("fade");var l="function"==typeof this.config.placement?this.config.placement.call(this,a,this.element):this.config.placement,u=this._getAttachment(l);this.addAttachmentClass(u);var f=this._getContainer();o.default(a).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(a).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new r.default(this.element,a,this._getPopperConfig(u)),o.default(a).addClass("show"),o.default(a).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),"out"===e&&t._leave(null,t)};if(o.default(this.tip).hasClass("fade")){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),r=function(){"show"!==e._hoverState&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass("show"),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass("fade")){var a=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,r).emulateTransitionEnd(a)}else r();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Q(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return l({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=l({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return z[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n="hover"===e?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i="hover"===e?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),o.default(e.getTipElement()).hasClass("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){"show"===e._hoverState&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){"out"===e._hoverState&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Y.indexOf(t)&&delete e[t]})),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d.typeCheckConfig(W,t,this.constructor.DefaultType),t.sanitize&&(t.template=Q(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(V);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.tooltip"),r="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,r),n.data("bs.tooltip",i)),"string"==typeof e)){if(void 0===i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return K}},{key:"NAME",get:function(){return W}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return $}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return X}}]),t}();o.default.fn[W]=G._jQueryInterface,o.default.fn[W].Constructor=G,o.default.fn[W].noConflict=function(){return o.default.fn[W]=U,G._jQueryInterface};var J="popover",Z=o.default.fn[J],tt=new RegExp("(^|\\s)bs-popover\\S+","g"),et=l({},G.Default,{placement:"right",trigger:"click",content:"",template:''}),nt=l({},G.DefaultType,{content:"(string|element|function)"}),it={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},ot=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,u(e,n);var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},r.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},r.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(tt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data("bs.popover"),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data("bs.popover",e)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},s(i,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return et}},{key:"NAME",get:function(){return J}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return it}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return nt}}]),i}(G);o.default.fn[J]=ot._jQueryInterface,o.default.fn[J].Constructor=ot,o.default.fn[J].noConflict=function(){return o.default.fn[J]=Z,ot._jQueryInterface};var rt="scrollspy",at=o.default.fn[rt],st={offset:10,method:"auto",target:""},lt={offset:"number",method:"string",target:"(string|element)"},ut=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":"position",n="auto"===this._config.method?e:this._config.method,i="position"===n?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,r=d.getSelectorFromElement(t);if(r&&(e=document.querySelector(r)),e){var a=e.getBoundingClientRect();if(a.width||a.height)return[o.default(e)[n]().top+i,r]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){o.default.removeData(this._element,"bs.scrollspy"),o.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=l({},st,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(rt),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(rt,t,lt),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&(void 0===this._offsets[o+1]||t li > .active":".active";n=(n=o.default.makeArray(o.default(i).find(a)))[n.length-1]}var s=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),l=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(s),o.default(this._element).trigger(l),!l.isDefaultPrevented()&&!s.isDefaultPrevented()){r&&(e=document.querySelector(r)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,"bs.tab"),this._element=null},e._activate=function(t,e,n){var i=this,r=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(".active"):o.default(e).find("> li > .active"))[0],a=n&&r&&o.default(r).hasClass("fade"),s=function(){return i._transitionComplete(t,r,n)};if(r&&a){var l=d.getTransitionDurationFromElement(r);o.default(r).removeClass("show").one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass("active");var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}o.default(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains("fade")&&t.classList.add("show");var r=t.parentNode;if(r&&"LI"===r.nodeName&&(r=r.parentNode),r&&o.default(r).hasClass("dropdown-menu")){var a=o.default(t).closest(".dropdown")[0];if(a){var s=[].slice.call(a.querySelectorAll(".dropdown-toggle"));o.default(s).addClass("active")}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.tab");if(i||(i=new t(this),n.data("bs.tab",i)),"string"==typeof e){if(void 0===i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),dt._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=dt._jQueryInterface,o.default.fn.tab.Constructor=dt,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=ft,dt._jQueryInterface};var ct="toast",ht=o.default.fn[ct],pt={animation:!0,autohide:!0,delay:500},mt={animation:"boolean",autohide:"boolean",delay:"number"},gt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),d.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains("show")){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),o.default(this._element).off("click.dismiss.bs.toast"),o.default.removeData(this._element,"bs.toast"),this._element=null,this._config=null},e._getConfig=function(t){return t=l({},pt,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig(ct,t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add("hide"),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.toast");if(i||(i=new t(this,"object"==typeof e&&e),n.data("bs.toast",i)),"string"==typeof e){if(void 0===i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},s(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"DefaultType",get:function(){return mt}},{key:"Default",get:function(){return pt}}]),t}();o.default.fn[ct]=gt._jQueryInterface,o.default.fn[ct].Constructor=gt,o.default.fn[ct].noConflict=function(){return o.default.fn[ct]=ht,gt._jQueryInterface},t.Alert=h,t.Button=m,t.Carousel=E,t.Collapse=D,t.Dropdown=j,t.Modal=R,t.Popover=ot,t.Scrollspy=ut,t.Tab=dt,t.Toast=gt,t.Tooltip=G,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})}(e,n(0),n(1))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){"use strict";n.r(e);n(0),n(3),n.p;$((function(){var t=document.querySelector("div.bd-sidebar");let e=parseInt(sessionStorage.getItem("sidebar-scroll-top"),10);if(isNaN(e)){var n=document.getElementById("bd-docs-nav").querySelectorAll(".active");if(n.length>0){var i=n[n.length-1],o=i.getBoundingClientRect().y-t.getBoundingClientRect().y;if(i.getBoundingClientRect().y>.5*window.innerHeight){let e=.25;t.scrollTop=o-t.clientHeight*e,console.log("[PST]: Scrolled sidebar using last active link...")}}}else t.scrollTop=e,console.log("[PST]: Scrolled sidebar using stored browser position...");window.addEventListener("beforeunload",()=>{sessionStorage.setItem("sidebar-scroll-top",t.scrollTop)})})),$((function(){$(window).on("activate.bs.scrollspy",(function(){document.querySelectorAll("#bd-toc-nav a").forEach(t=>{t.parentElement.classList.remove("active")});document.querySelectorAll("#bd-toc-nav a.active").forEach(t=>{t.parentElement.classList.add("active")})}))}))}]); \ No newline at end of file diff --git a/_static/scripts/sphinx-book-theme.js b/_static/scripts/sphinx-book-theme.js new file mode 100644 index 0000000..a8a305e --- /dev/null +++ b/_static/scripts/sphinx-book-theme.js @@ -0,0 +1,2 @@ +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";n.r(t);n.p;var o=e=>{"loading"!=document.readyState?e():document.addEventListener?document.addEventListener("DOMContentLoaded",e):document.attachEvent("onreadystatechange",(function(){"complete"==document.readyState&&e()}))};window.initThebeSBT=()=>{var e=$("div.section h1")[0];$(e).next().hasClass("thebe-launch-button")||$("").insertAfter($(e)),initThebe()},window.printPdf=e=>{let t=$(e).attr("aria-describedby"),n=$("#"+t).detach();window.print(),$("body").append(n)},window.toggleFullScreen=()=>{var e=document.fullscreenElement&&null!==document.fullscreenElement||document.webkitFullscreenElement&&null!==document.webkitFullscreenElement;let t=document.documentElement;e?(console.log("[SBT]: Exiting full screen"),document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen()):(console.log("[SBT]: Entering full screen"),t.requestFullscreen?t.requestFullscreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen())},o(()=>{$(document).ready((function(){$('[data-toggle="tooltip"]').tooltip({trigger:"hover",delay:{show:500,hide:100}})}))}),o(()=>{var e=document.getElementById("site-navigation"),t=e.querySelectorAll(".active"),n=t[t.length-1];void 0!==n&&n.offsetTop>.5*$(window).height()&&(e.scrollTop=n.offsetTop-.2*$(window).height())}),o(()=>{var e=[];let t=new IntersectionObserver((t,n)=>{t.forEach(t=>{if(t.isIntersecting)e.push(t.target);else for(let n=0;n0?$("div.bd-toc").removeClass("show"):$("div.bd-toc").addClass("show")});let n=[];["marginnote","sidenote","margin","margin-caption","full-width","sidebar","popout"].forEach(e=>{n.push("."+e,".tag_"+e,"."+e.replace("-","_"),".tag_"+e.replace("-","_"))}),document.querySelectorAll(n.join(", ")).forEach(e=>{t.observe(e)}),new IntersectionObserver((e,t)=>{e[0].boundingClientRect.y<0?document.body.classList.add("scrolled"):document.body.classList.remove("scrolled")}).observe(document.querySelector(".sbt-scroll-pixel-helper"))}),o((function(){new MutationObserver((e,t)=>{e.forEach(e=>{0!==e.addedNodes.length&&void 0!==e.addedNodes[0].data&&-1!=e.addedNodes[0].data.search("Inserted RTD Footer")&&e.addedNodes.forEach(e=>{document.getElementById("rtd-footer-container").append(e)})})}).observe(document.body,{childList:!0})}))}]); +//# sourceMappingURL=sphinx-book-theme.js.map \ No newline at end of file diff --git a/_static/scripts/sphinx-book-theme.js.map b/_static/scripts/sphinx-book-theme.js.map new file mode 100644 index 0000000..dccd768 --- /dev/null +++ b/_static/scripts/sphinx-book-theme.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/sphinx_book_theme/assets/styles/index.scss","webpack:///./src/sphinx_book_theme/assets/scripts/index.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","sbRunWhenDOMLoaded","cb","document","readyState","addEventListener","attachEvent","window","initThebeSBT","title","$","next","hasClass","insertAfter","initThebe","printPdf","el","tooltipID","attr","tooltipTextDiv","detach","print","append","toggleFullScreen","isInFullScreen","fullscreenElement","webkitFullscreenElement","docElm","documentElement","console","log","exitFullscreen","webkitExitFullscreen","requestFullscreen","webkitRequestFullscreen","ready","tooltip","trigger","delay","show","hide","navbar","getElementById","active_pages","querySelectorAll","active_page","length","undefined","offsetTop","height","scrollTop","onScreenItems","tocObserver","IntersectionObserver","entries","observer","forEach","entry","isIntersecting","push","target","ii","splice","removeClass","addClass","marginSelector","replace","join","observe","boundingClientRect","y","body","classList","add","remove","querySelector","MutationObserver","mutationList","mutation","addedNodes","data","search","node","childList"],"mappings":"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","file":"scripts/sphinx-book-theme.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","export default __webpack_public_path__ + \"styles/sphinx-book-theme.css\";","// Import CSS variables\n// ref: https://css-tricks.com/getting-javascript-to-talk-to-css-and-sass/\nimport \"../styles/index.scss\";\n\n/**\n * A helper function to load scripts when the DOM is loaded.\n * This waits for everything to be on the page first before running, since\n * some functionality doesn't behave properly until everything is ready.\n */\nvar sbRunWhenDOMLoaded = (cb) => {\n if (document.readyState != \"loading\") {\n cb();\n } else if (document.addEventListener) {\n document.addEventListener(\"DOMContentLoaded\", cb);\n } else {\n document.attachEvent(\"onreadystatechange\", function () {\n if (document.readyState == \"complete\") cb();\n });\n }\n};\n\n/**\n * Toggle full-screen with button\n *\n * There are some browser-specific hacks in here:\n * - Safari requires a `webkit` prefix, so this uses conditionals to check for that\n * ref: https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API\n */\nvar toggleFullScreen = () => {\n var isInFullScreen =\n (document.fullscreenElement && document.fullscreenElement !== null) ||\n (document.webkitFullscreenElement &&\n document.webkitFullscreenElement !== null);\n let docElm = document.documentElement;\n if (!isInFullScreen) {\n console.log(\"[SBT]: Entering full screen\");\n if (docElm.requestFullscreen) {\n docElm.requestFullscreen();\n } else if (docElm.webkitRequestFullscreen) {\n docElm.webkitRequestFullscreen();\n }\n } else {\n console.log(\"[SBT]: Exiting full screen\");\n if (document.exitFullscreen) {\n document.exitFullscreen();\n } else if (document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n }\n};\n\n/**\n * Sidebar scroll on load.\n *\n * Detect the active page in the sidebar, and scroll so that it is centered on\n * the screen.\n */\nvar scrollToActive = () => {\n var navbar = document.getElementById(\"site-navigation\");\n var active_pages = navbar.querySelectorAll(\".active\");\n var active_page = active_pages[active_pages.length - 1];\n // Only scroll the navbar if the active link is lower than 50% of the page\n if (\n active_page !== undefined &&\n active_page.offsetTop > $(window).height() * 0.5\n ) {\n navbar.scrollTop = active_page.offsetTop - $(window).height() * 0.2;\n }\n};\n\n/**\n * Called when the \"print to PDF\" button is clicked.\n * This is a hack to prevent tooltips from showing up in the printed PDF.\n */\nvar printPdf = (el) => {\n // Detach the tooltip text from DOM to hide in PDF\n // and then reattach it for HTML\n let tooltipID = $(el).attr(\"aria-describedby\");\n let tooltipTextDiv = $(\"#\" + tooltipID).detach();\n window.print();\n $(\"body\").append(tooltipTextDiv);\n};\n\n/**\n * Manage scrolling behavior. This is primarily two things:\n *\n * 1. Hide the Table of Contents any time sidebar content is on the screen.\n *\n * This will be triggered any time a sidebar item enters or exits the screen.\n * It adds/removes items from an array if they have entered the screen, and\n * removes them when they exit the screen. It hides the TOC if anything is\n * on-screen.\n *\n * ref: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API\n *\n * 2. Add a `scrolled` class to to trigger CSS changes.\n */\nvar initTocHide = () => {\n var onScreenItems = [];\n let hideTocCallback = (entries, observer) => {\n // Check whether any sidebar item is displayed\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n // If an element just came on screen, add it our list\n onScreenItems.push(entry.target);\n } else {\n // Otherwise, if it's in our list then remove it\n for (let ii = 0; ii < onScreenItems.length; ii++) {\n if (onScreenItems[ii] === entry.target) {\n onScreenItems.splice(ii, 1);\n break;\n }\n }\n }\n });\n\n // Hide the TOC if any margin content is displayed on the screen\n if (onScreenItems.length > 0) {\n $(\"div.bd-toc\").removeClass(\"show\");\n } else {\n $(\"div.bd-toc\").addClass(\"show\");\n }\n };\n let manageScrolledClassOnBody = (entries, observer) => {\n // The pixel is at the top, so if we're < 0 that it means we've scrolled\n if (entries[0].boundingClientRect.y < 0) {\n document.body.classList.add(\"scrolled\");\n } else {\n document.body.classList.remove(\"scrolled\");\n }\n };\n\n // Set up the intersection observer to watch all margin content\n let tocObserver = new IntersectionObserver(hideTocCallback);\n // TODO: deprecate popout after v0.5.0\n const selectorClasses = [\n \"marginnote\",\n \"sidenote\",\n \"margin\",\n \"margin-caption\",\n \"full-width\",\n \"sidebar\",\n \"popout\",\n ];\n let marginSelector = [];\n selectorClasses.forEach((ii) => {\n // Use three permutations of each class name because `tag_` and `_` used to be supported\n marginSelector.push(\n ...[\n `.${ii}`,\n `.tag_${ii}`,\n `.${ii.replace(\"-\", \"_\")}`,\n `.tag_${ii.replace(\"-\", \"_\")}`,\n ]\n );\n });\n document.querySelectorAll(marginSelector.join(\", \")).forEach((ii) => {\n tocObserver.observe(ii);\n });\n\n // Set up the observer to check if we've scrolled from top of page\n let scrollObserver = new IntersectionObserver(manageScrolledClassOnBody);\n scrollObserver.observe(document.querySelector(\".sbt-scroll-pixel-helper\"));\n};\n\n/**\n * Activate Thebe with a custom button click.\n */\nvar initThebeSBT = () => {\n var title = $(\"div.section h1\")[0];\n if (!$(title).next().hasClass(\"thebe-launch-button\")) {\n $(\"\").insertAfter($(title));\n }\n initThebe();\n};\n\n/**\n * Use Bootstrap helper function to enable tooltips.\n */\nvar initTooltips = () => {\n $(document).ready(function () {\n $('[data-toggle=\"tooltip\"]').tooltip({\n trigger: \"hover\",\n delay: { show: 500, hide: 100 },\n });\n });\n};\n\n/**\n * MutationObserver to move the ReadTheDocs button\n */\nfunction initRTDObserver() {\n const mutatedCallback = (mutationList, observer) => {\n mutationList.forEach((mutation) => {\n // Check whether the mutation is for RTD, which will have a specific structure\n if (mutation.addedNodes.length === 0) {\n return;\n }\n if (mutation.addedNodes[0].data === undefined) {\n return;\n }\n if (mutation.addedNodes[0].data.search(\"Inserted RTD Footer\") != -1) {\n mutation.addedNodes.forEach((node) => {\n document.getElementById(\"rtd-footer-container\").append(node);\n });\n }\n });\n };\n\n const observer = new MutationObserver(mutatedCallback);\n const config = { childList: true };\n observer.observe(document.body, config);\n}\n\n/**\n * Set up callback functions for UI click actions\n */\nwindow.initThebeSBT = initThebeSBT;\nwindow.printPdf = printPdf;\nwindow.toggleFullScreen = toggleFullScreen;\n\n/**\n * Set up functions to load when the DOM is ready\n */\nsbRunWhenDOMLoaded(initTooltips);\nsbRunWhenDOMLoaded(scrollToActive);\nsbRunWhenDOMLoaded(initTocHide);\nsbRunWhenDOMLoaded(initRTDObserver);\n"],"sourceRoot":""} \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 0000000..0a44e85 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,525 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +if (!Scorer) { + /** + * Simple result scoring code. + */ + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [filename, title, anchor, descr, score] + // and returns the new score. + /* + score: function(result) { + return result[4]; + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: {0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5}, // used to be unimportantResults + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2 + }; +} + +if (!splitQuery) { + function splitQuery(query) { + return query.split(/\s+/); + } +} + +/** + * Search Module + */ +var Search = { + + _index : null, + _queued_query : null, + _pulse_status : -1, + + htmlToText : function(htmlString) { + var virtualDocument = document.implementation.createHTMLDocument('virtual'); + var htmlElement = $(htmlString, virtualDocument); + htmlElement.find('.headerlink').remove(); + docContent = htmlElement.find('[role=main]')[0]; + if(docContent === undefined) { + console.warn("Content block not found. Sphinx search tries to obtain it " + + "via '[role=main]'. Could you check your theme or template."); + return ""; + } + return docContent.textContent || docContent.innerText; + }, + + init : function() { + var params = $.getQueryParameters(); + if (params.q) { + var query = params.q[0]; + $('input[name="q"]')[0].value = query; + this.performSearch(query); + } + }, + + loadIndex : function(url) { + $.ajax({type: "GET", url: url, data: null, + dataType: "script", cache: true, + complete: function(jqxhr, textstatus) { + if (textstatus != "success") { + document.getElementById("searchindexloader").src = url; + } + }}); + }, + + setIndex : function(index) { + var q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex : function() { + return this._index !== null; + }, + + deferQuery : function(query) { + this._queued_query = query; + }, + + stopPulse : function() { + this._pulse_status = 0; + }, + + startPulse : function() { + if (this._pulse_status >= 0) + return; + function pulse() { + var i; + Search._pulse_status = (Search._pulse_status + 1) % 4; + var dotString = ''; + for (i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.text(dotString); + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + } + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch : function(query) { + // create the required interface elements + this.out = $('#search-results'); + this.title = $('

' + _('Searching') + '

').appendTo(this.out); + this.dots = $('').appendTo(this.title); + this.status = $('

 

').appendTo(this.out); + this.output = $('