From 7a30cf57981f32fb6b876fe167bb17b3c6946d6d Mon Sep 17 00:00:00 2001 From: S John CD Date: Thu, 7 Mar 2024 22:05:41 +0000 Subject: [PATCH] Overhaul: add Dev Containers, move doc_src to docs, migrate link to https:, lint markdown --- .devcontainer/Dockerfile | 90 + .devcontainer/compose-ci.yaml | 8 + .devcontainer/compose.override.yaml | 14 + .devcontainer/compose.yaml | 14 + .devcontainer/devcontainer.json | 60 + .dockerignore | 35 + .gitattributes | 144 +- .github/dependabot.yml | 12 + .github/workflows/ci.yaml | 29 + .gitignore | 271 +- .vscode/settings.json | 3 + README.md | 49 +- docs/404.html | 1839 --------- .../Big_Data/Hadoop_Ecosystem.md | 19 +- docs/Big_Data/Hadoop_Ecosystem/index.html | 2010 ---------- .../Big_Data/Install_Spark_2.3_Locally.md | 15 +- .../Install_Spark_2.3_Locally/index.html | 2085 ---------- {docs_src => docs}/Big_Data/Spark_APIs.md | 18 +- docs/Big_Data/Spark_APIs/index.html | 2084 ---------- {docs_src => docs}/Big_Data/Spark_Basics.md | 13 +- docs/Big_Data/Spark_Basics/index.html | 2051 ---------- .../Spark_Development_with_sbt_and_InteliJ.md | 46 + .../index.html | 2057 ---------- .../Big_Data/Spark_on_AWS_EMR.md | 36 +- docs/Big_Data/Spark_on_AWS_EMR/index.html | 2104 ---------- {docs_src => docs}/Big_Data/Spark_on_EC2.md | 4 +- docs/Big_Data/Spark_on_EC2/index.html | 2018 ---------- .../Big_Data/Spark_on_Kubernetes.md | 17 +- docs/Big_Data/Spark_on_Kubernetes/index.html | 2077 ---------- {docs_src => docs}/Cloud/AWS.md | 57 +- docs/Cloud/AWS/index.html | 2211 ----------- {docs_src => docs}/Cloud/AWS_Lambda.md | 2 - docs/Cloud/AWS_Lambda/index.html | 1959 ---------- {docs_src => docs}/Cloud/Serverless.md | 1 - docs/Cloud/Serverless/index.html | 2044 ---------- .../Containers/Debug_Kubernetes.md | 10 +- docs/Containers/Debug_Kubernetes/index.html | 2007 ---------- .../Deploy_to_Kubernetes (Helm).md | 30 +- .../Deploy_to_Kubernetes (Helm)/index.html | 2213 ----------- .../Containers/Deploy_to_Kubernetes.md | 30 +- .../Deploy_to_Kubernetes/index.html | 2147 ---------- {docs_src => docs}/Containers/Docker.md | 53 +- docs/Containers/Docker/index.html | 2172 ----------- .../Containers/Helm_Chart_Creation.md | 2 +- .../Containers/Helm_Chart_Creation/index.html | 2015 ---------- .../Containers/Kubernetes_Cheatsheet.md | 14 +- .../Kubernetes_Cheatsheet/index.html | 2023 ---------- .../Containers/Kubernetes_Concepts.md | 16 +- .../Containers/Kubernetes_Concepts/index.html | 1924 --------- .../Containers/Kubernetes_Examples.md | 0 .../Containers/Kubernetes_Examples/index.html | 2054 ---------- .../Minikube_Install_in_Ubuntu_on_Windows.md | 6 +- .../index.html | 1984 ---------- .../Containers/Minikube_Install_on_Windows.md | 25 +- .../Minikube_Install_on_Windows/index.html | 2188 ----------- .../Data_Science/Data_Manipulation.md | 8 +- .../Data_Science/Data_Manipulation/index.html | 1982 ---------- .../Data_Science/Data_Visualization.md | 18 +- .../Data_Visualization/index.html | 2041 ---------- .../Data_Science/Deep_Learning.md | 25 +- docs/Data_Science/Deep_Learning/index.html | 2006 ---------- .../Data_Science/Dimensionality_Reduction.md | 4 +- .../Dimensionality_Reduction/index.html | 1960 ---------- {docs_src => docs}/Data_Science/Keras.md | 4 +- docs/Data_Science/Keras/index.html | 1932 --------- .../Data_Science/Machine_Learning.md | 42 +- docs/Data_Science/Machine_Learning/index.html | 1968 ---------- .../Data_Science/Recommenders.md | 3 +- docs/Data_Science/Recommenders/index.html | 1960 ---------- .../Data_Science/scikit-learn.md | 0 docs/Data_Science/scikit-learn/index.html | 1958 ---------- {docs_src => docs}/Databases/Mongodb.md | 64 +- docs/Databases/Mongodb/index.html | 2145 ---------- {docs_src => docs}/Databases/Redshift.md | 13 +- docs/Databases/Redshift/index.html | 1982 ---------- {docs_src => docs}/Databases/SQL.md | 1 + docs/Databases/SQL/index.html | 3006 -------------- {docs_src => docs}/DevOps/CloudFormation.md | 54 +- docs/DevOps/CloudFormation/index.html | 2223 ----------- {docs_src => docs}/DevOps/Git.md | 104 +- docs/DevOps/Git/index.html | 2359 ----------- .../DevOps/Orchestrator_Scheduler.md | 6 +- docs/DevOps/Orchestrator_Scheduler/index.html | 1990 ---------- {docs_src => docs}/Java/Gradle.md | 0 docs/Java/Gradle/index.html | 2246 ----------- docs/Java/Java.md | 49 + docs/Java/Java/index.html | 2025 ---------- {docs_src => docs}/Java/Log4j.md | 35 +- docs/Java/Log4j/index.html | 2111 ---------- {docs_src => docs}/Java/Maven.md | 12 +- docs/Java/Maven/index.html | 2145 ---------- {docs_src => docs}/Java/Spring.md | 2 - docs/Java/Spring/index.html | 1965 ---------- {docs_src => docs}/Linux/Linux.md | 21 +- docs/Linux/Linux/index.html | 2206 ----------- docs/Linux/Virtualization.md | 11 + docs/Linux/Virtualization/index.html | 1920 --------- .../Markup_and_Documentation/Jekyll.md | 50 +- .../Jekyll/index.html | 2043 ---------- .../Markup_and_Documentation/Markdown.md | 106 +- .../Markdown/index.html | 2180 ----------- .../Markup_and_Documentation/MkDocs.md | 28 +- .../MkDocs/index.html | 2030 ---------- .../reStructuredText.md | 347 ++ .../reStructuredText/index.html | 2371 ------------ .../Microservices/Microservices.md | 7 +- docs/Microservices/Microservices/index.html | 2003 ---------- .../Privacy/Privacy_engineering.md | 0 docs/Privacy/Privacy_engineering/index.html | 1963 ---------- {docs_src => docs}/Python/Flask.md | 2 +- docs/Python/Flask/index.html | 1966 ---------- {docs_src => docs}/Python/Jupyter.md | 54 +- docs/Python/Jupyter/index.html | 2066 ---------- {docs_src => docs}/Python/Matplotlib.md | 26 +- docs/Python/Matplotlib/index.html | 2020 ---------- {docs_src => docs}/Python/Python.md | 10 +- docs/Python/Python/index.html | 2053 ---------- {docs_src => docs}/Python/Python3.md | 21 +- docs/Python/Python3/index.html | 2255 ----------- {docs_src => docs}/Scala/Akka.md | 6 +- docs/Scala/Akka/index.html | 2079 ---------- {docs_src => docs}/Scala/Play_Framework.md | 7 +- docs/Scala/Play_Framework/index.html | 2007 ---------- {docs_src => docs}/Scala/Scala_Collections.md | 136 +- docs/Scala/Scala_Collections/index.html | 2417 ------------ .../Scala/Scala_Database_Access.md | 17 +- docs/Scala/Scala_Database_Access/index.html | 1983 ---------- .../Scala/Scala_Design_Patterns.md | 68 +- docs/Scala/Scala_Design_Patterns/index.html | 2367 ----------- .../Scala/Scala_Generalities.md | 12 +- docs/Scala/Scala_Generalities/index.html | 2047 ---------- {docs_src => docs}/Scala/Scala_Language.md | 225 +- docs/Scala/Scala_Language/index.html | 3445 ----------------- {docs_src => docs}/Scala/Scala_Testing.md | 67 +- docs/Scala/Scala_Testing/index.html | 2139 ---------- {docs_src => docs}/Scala/Scala_Types.md | 17 +- docs/Scala/Scala_Types/index.html | 2345 ----------- {docs_src => docs}/Scala/Scaladoc.md | 73 +- docs/Scala/Scaladoc/index.html | 2155 ----------- {docs_src => docs}/Scala/sbt.md | 24 +- docs/Scala/sbt/index.html | 2127 ---------- {docs_src => docs}/Search/ElasticSearch.md | 256 +- docs/Search/ElasticSearch/index.html | 2717 ------------- {docs_src => docs}/Search/Logstash.md | 52 +- docs/Search/Logstash/index.html | 2144 ---------- docs/Search/search_index.json | 1 - .../Software_Development/Development_Tools.md | 38 +- .../Development_Tools/index.html | 2290 ----------- .../Software_Development/Eclipse.md | 8 +- docs/Software_Development/Eclipse/index.html | 1992 ---------- .../Software_Development/IntelliJ.md | 0 docs/Software_Development/IntelliJ/index.html | 1971 ---------- {docs_src => docs}/Web/Bootstrap.md | 5 +- docs/Web/Bootstrap/index.html | 2024 ---------- {docs_src => docs}/Web/CORS.md | 12 +- docs/Web/CORS/index.html | 2015 ---------- {docs_src => docs}/Web/jQuery.md | 34 +- docs/Web/jQuery/index.html | 2795 ------------- .../Windows/Command_Prompt_Here.md | 5 +- docs/Windows/Command_Prompt_Here/index.html | 1903 --------- docs/assets/images/favicon.png | Bin 1870 -> 0 bytes .../assets/javascripts/bundle.6ced434e.min.js | 2 - .../javascripts/bundle.6ced434e.min.js.map | 1 - .../javascripts/lunr/min/lunr.ar.min.js | 1 - .../javascripts/lunr/min/lunr.da.min.js | 18 - .../javascripts/lunr/min/lunr.de.min.js | 18 - .../javascripts/lunr/min/lunr.du.min.js | 18 - .../javascripts/lunr/min/lunr.es.min.js | 18 - .../javascripts/lunr/min/lunr.fi.min.js | 18 - .../javascripts/lunr/min/lunr.fr.min.js | 18 - .../javascripts/lunr/min/lunr.hu.min.js | 18 - .../javascripts/lunr/min/lunr.it.min.js | 18 - .../javascripts/lunr/min/lunr.ja.min.js | 1 - .../javascripts/lunr/min/lunr.jp.min.js | 1 - .../javascripts/lunr/min/lunr.multi.min.js | 1 - .../javascripts/lunr/min/lunr.nl.min.js | 18 - .../javascripts/lunr/min/lunr.no.min.js | 18 - .../javascripts/lunr/min/lunr.pt.min.js | 18 - .../javascripts/lunr/min/lunr.ro.min.js | 18 - .../javascripts/lunr/min/lunr.ru.min.js | 18 - .../lunr/min/lunr.stemmer.support.min.js | 1 - .../javascripts/lunr/min/lunr.sv.min.js | 18 - .../javascripts/lunr/min/lunr.tr.min.js | 18 - .../javascripts/lunr/min/lunr.vi.min.js | 1 - docs/assets/javascripts/lunr/tinyseg.min.js | 1 - .../assets/javascripts/vendor.08c56446.min.js | 16 - .../javascripts/vendor.08c56446.min.js.map | 1 - .../javascripts/worker/search.8c7e0a7e.min.js | 59 - .../worker/search.8c7e0a7e.min.js.map | 1 - docs/assets/stylesheets/main.3b61ea93.min.css | 3 - .../stylesheets/main.3b61ea93.min.css.map | 1 - .../stylesheets/palette.39b8e14a.min.css | 3 - .../stylesheets/palette.39b8e14a.min.css.map | 1 - {docs_src => docs}/dotNET/ASPdotNET.md | 23 +- docs/dotNET/ASPdotNET/index.html | 2152 ---------- {docs_src => docs}/dotNET/AkkadotNET.md | 170 +- docs/dotNET/AkkadotNET/index.html | 2114 ---------- {docs_src => docs}/dotNET/C#.md | 17 +- docs/dotNET/C#/index.html | 2053 ---------- {docs_src => docs}/dotNET/Multithreading.md | 0 docs/dotNET/Multithreading/index.html | 1962 ---------- {docs_src => docs}/dotNET/WPF.md | 21 +- docs/dotNET/WPF/index.html | 2108 ---------- docs/index.html | 1880 --------- {docs_src => docs}/index.md | 4 +- docs/sitemap.xml | 319 -- docs/sitemap.xml.gz | Bin 989 -> 0 bytes .../Spark_Development_with_sbt_and_InteliJ.md | 50 - docs_src/Java/Java.md | 50 - docs_src/Linux/Virtualization.md | 12 - .../reStructuredText.md | 344 -- drafts/Analytical_Tools.md | 88 +- drafts/Azure.md | 2 +- drafts/Citizen_developer_tools.md | 5 +- drafts/Cloud_Computing.md | 7 +- drafts/DataScience.md | 28 +- drafts/Data_Visualization.md | 8 +- drafts/Java.md | 6 +- drafts/Kong.md | 4 +- drafts/Logging.md | 4 +- drafts/Play_Framework2.md | 18 +- drafts/Scala3.md | 6 +- drafts/Stream_Processing.md | 3 +- drafts/Terraform2.md | 7 +- drafts/Windows_Tools.md | 3 - mkdocs.yml | 139 +- 226 files changed, 2435 insertions(+), 172178 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/compose-ci.yaml create mode 100644 .devcontainer/compose.override.yaml create mode 100644 .devcontainer/compose.yaml create mode 100644 .devcontainer/devcontainer.json create mode 100644 .dockerignore create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yaml create mode 100644 .vscode/settings.json delete mode 100644 docs/404.html rename {docs_src => docs}/Big_Data/Hadoop_Ecosystem.md (62%) delete mode 100644 docs/Big_Data/Hadoop_Ecosystem/index.html rename {docs_src => docs}/Big_Data/Install_Spark_2.3_Locally.md (93%) delete mode 100644 docs/Big_Data/Install_Spark_2.3_Locally/index.html rename {docs_src => docs}/Big_Data/Spark_APIs.md (81%) delete mode 100644 docs/Big_Data/Spark_APIs/index.html rename {docs_src => docs}/Big_Data/Spark_Basics.md (85%) delete mode 100644 docs/Big_Data/Spark_Basics/index.html create mode 100644 docs/Big_Data/Spark_Development_with_sbt_and_InteliJ.md delete mode 100644 docs/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html rename {docs_src => docs}/Big_Data/Spark_on_AWS_EMR.md (71%) delete mode 100644 docs/Big_Data/Spark_on_AWS_EMR/index.html rename {docs_src => docs}/Big_Data/Spark_on_EC2.md (91%) delete mode 100644 docs/Big_Data/Spark_on_EC2/index.html rename {docs_src => docs}/Big_Data/Spark_on_Kubernetes.md (89%) delete mode 100644 docs/Big_Data/Spark_on_Kubernetes/index.html rename {docs_src => docs}/Cloud/AWS.md (73%) delete mode 100644 docs/Cloud/AWS/index.html rename {docs_src => docs}/Cloud/AWS_Lambda.md (99%) delete mode 100644 docs/Cloud/AWS_Lambda/index.html rename {docs_src => docs}/Cloud/Serverless.md (99%) delete mode 100644 docs/Cloud/Serverless/index.html rename {docs_src => docs}/Containers/Debug_Kubernetes.md (85%) delete mode 100644 docs/Containers/Debug_Kubernetes/index.html rename {docs_src => docs}/Containers/Deploy_to_Kubernetes (Helm).md (89%) delete mode 100644 docs/Containers/Deploy_to_Kubernetes (Helm)/index.html rename {docs_src => docs}/Containers/Deploy_to_Kubernetes.md (84%) delete mode 100644 docs/Containers/Deploy_to_Kubernetes/index.html rename {docs_src => docs}/Containers/Docker.md (76%) delete mode 100644 docs/Containers/Docker/index.html rename {docs_src => docs}/Containers/Helm_Chart_Creation.md (98%) delete mode 100644 docs/Containers/Helm_Chart_Creation/index.html rename {docs_src => docs}/Containers/Kubernetes_Cheatsheet.md (86%) delete mode 100644 docs/Containers/Kubernetes_Cheatsheet/index.html rename {docs_src => docs}/Containers/Kubernetes_Concepts.md (60%) delete mode 100644 docs/Containers/Kubernetes_Concepts/index.html rename {docs_src => docs}/Containers/Kubernetes_Examples.md (100%) delete mode 100644 docs/Containers/Kubernetes_Examples/index.html rename {docs_src => docs}/Containers/Minikube_Install_in_Ubuntu_on_Windows.md (96%) delete mode 100644 docs/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html rename {docs_src => docs}/Containers/Minikube_Install_on_Windows.md (88%) delete mode 100644 docs/Containers/Minikube_Install_on_Windows/index.html rename {docs_src => docs}/Data_Science/Data_Manipulation.md (82%) delete mode 100644 docs/Data_Science/Data_Manipulation/index.html rename {docs_src => docs}/Data_Science/Data_Visualization.md (61%) delete mode 100644 docs/Data_Science/Data_Visualization/index.html rename {docs_src => docs}/Data_Science/Deep_Learning.md (50%) delete mode 100644 docs/Data_Science/Deep_Learning/index.html rename {docs_src => docs}/Data_Science/Dimensionality_Reduction.md (70%) delete mode 100644 docs/Data_Science/Dimensionality_Reduction/index.html rename {docs_src => docs}/Data_Science/Keras.md (78%) delete mode 100644 docs/Data_Science/Keras/index.html rename {docs_src => docs}/Data_Science/Machine_Learning.md (59%) delete mode 100644 docs/Data_Science/Machine_Learning/index.html rename {docs_src => docs}/Data_Science/Recommenders.md (99%) delete mode 100644 docs/Data_Science/Recommenders/index.html rename {docs_src => docs}/Data_Science/scikit-learn.md (100%) delete mode 100644 docs/Data_Science/scikit-learn/index.html rename {docs_src => docs}/Databases/Mongodb.md (81%) delete mode 100644 docs/Databases/Mongodb/index.html rename {docs_src => docs}/Databases/Redshift.md (62%) delete mode 100644 docs/Databases/Redshift/index.html rename {docs_src => docs}/Databases/SQL.md (99%) delete mode 100644 docs/Databases/SQL/index.html rename {docs_src => docs}/DevOps/CloudFormation.md (77%) delete mode 100644 docs/DevOps/CloudFormation/index.html rename {docs_src => docs}/DevOps/Git.md (65%) delete mode 100644 docs/DevOps/Git/index.html rename {docs_src => docs}/DevOps/Orchestrator_Scheduler.md (66%) delete mode 100644 docs/DevOps/Orchestrator_Scheduler/index.html rename {docs_src => docs}/Java/Gradle.md (100%) delete mode 100644 docs/Java/Gradle/index.html create mode 100644 docs/Java/Java.md delete mode 100644 docs/Java/Java/index.html rename {docs_src => docs}/Java/Log4j.md (74%) delete mode 100644 docs/Java/Log4j/index.html rename {docs_src => docs}/Java/Maven.md (89%) delete mode 100644 docs/Java/Maven/index.html rename {docs_src => docs}/Java/Spring.md (99%) delete mode 100644 docs/Java/Spring/index.html rename {docs_src => docs}/Linux/Linux.md (76%) delete mode 100644 docs/Linux/Linux/index.html create mode 100644 docs/Linux/Virtualization.md delete mode 100644 docs/Linux/Virtualization/index.html rename {docs_src => docs}/Markup_and_Documentation/Jekyll.md (80%) delete mode 100644 docs/Markup_and_Documentation/Jekyll/index.html rename {docs_src => docs}/Markup_and_Documentation/Markdown.md (56%) delete mode 100644 docs/Markup_and_Documentation/Markdown/index.html rename {docs_src => docs}/Markup_and_Documentation/MkDocs.md (65%) delete mode 100644 docs/Markup_and_Documentation/MkDocs/index.html create mode 100644 docs/Markup_and_Documentation/reStructuredText.md delete mode 100644 docs/Markup_and_Documentation/reStructuredText/index.html rename {docs_src => docs}/Microservices/Microservices.md (51%) delete mode 100644 docs/Microservices/Microservices/index.html rename {docs_src => docs}/Privacy/Privacy_engineering.md (100%) delete mode 100644 docs/Privacy/Privacy_engineering/index.html rename {docs_src => docs}/Python/Flask.md (72%) delete mode 100644 docs/Python/Flask/index.html rename {docs_src => docs}/Python/Jupyter.md (85%) delete mode 100644 docs/Python/Jupyter/index.html rename {docs_src => docs}/Python/Matplotlib.md (70%) delete mode 100644 docs/Python/Matplotlib/index.html rename {docs_src => docs}/Python/Python.md (96%) delete mode 100644 docs/Python/Python/index.html rename {docs_src => docs}/Python/Python3.md (90%) delete mode 100644 docs/Python/Python3/index.html rename {docs_src => docs}/Scala/Akka.md (99%) delete mode 100644 docs/Scala/Akka/index.html rename {docs_src => docs}/Scala/Play_Framework.md (98%) delete mode 100644 docs/Scala/Play_Framework/index.html rename {docs_src => docs}/Scala/Scala_Collections.md (61%) delete mode 100644 docs/Scala/Scala_Collections/index.html rename {docs_src => docs}/Scala/Scala_Database_Access.md (51%) delete mode 100644 docs/Scala/Scala_Database_Access/index.html rename {docs_src => docs}/Scala/Scala_Design_Patterns.md (88%) delete mode 100644 docs/Scala/Scala_Design_Patterns/index.html rename {docs_src => docs}/Scala/Scala_Generalities.md (78%) delete mode 100644 docs/Scala/Scala_Generalities/index.html rename {docs_src => docs}/Scala/Scala_Language.md (80%) delete mode 100644 docs/Scala/Scala_Language/index.html rename {docs_src => docs}/Scala/Scala_Testing.md (64%) delete mode 100644 docs/Scala/Scala_Testing/index.html rename {docs_src => docs}/Scala/Scala_Types.md (96%) delete mode 100644 docs/Scala/Scala_Types/index.html rename {docs_src => docs}/Scala/Scaladoc.md (80%) delete mode 100644 docs/Scala/Scaladoc/index.html rename {docs_src => docs}/Scala/sbt.md (95%) delete mode 100644 docs/Scala/sbt/index.html rename {docs_src => docs}/Search/ElasticSearch.md (84%) delete mode 100644 docs/Search/ElasticSearch/index.html rename {docs_src => docs}/Search/Logstash.md (72%) delete mode 100644 docs/Search/Logstash/index.html delete mode 100644 docs/Search/search_index.json rename {docs_src => docs}/Software_Development/Development_Tools.md (69%) delete mode 100644 docs/Software_Development/Development_Tools/index.html rename {docs_src => docs}/Software_Development/Eclipse.md (88%) delete mode 100644 docs/Software_Development/Eclipse/index.html rename {docs_src => docs}/Software_Development/IntelliJ.md (100%) delete mode 100644 docs/Software_Development/IntelliJ/index.html rename {docs_src => docs}/Web/Bootstrap.md (93%) delete mode 100644 docs/Web/Bootstrap/index.html rename {docs_src => docs}/Web/CORS.md (99%) delete mode 100644 docs/Web/CORS/index.html rename {docs_src => docs}/Web/jQuery.md (94%) delete mode 100644 docs/Web/jQuery/index.html rename {docs_src => docs}/Windows/Command_Prompt_Here.md (94%) delete mode 100644 docs/Windows/Command_Prompt_Here/index.html delete mode 100644 docs/assets/images/favicon.png delete mode 100644 docs/assets/javascripts/bundle.6ced434e.min.js delete mode 100644 docs/assets/javascripts/bundle.6ced434e.min.js.map delete mode 100644 docs/assets/javascripts/lunr/min/lunr.ar.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.da.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.de.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.du.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.es.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.fi.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.fr.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.hu.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.it.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.ja.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.jp.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.multi.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.nl.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.no.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.pt.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.ro.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.ru.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.stemmer.support.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.sv.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.tr.min.js delete mode 100644 docs/assets/javascripts/lunr/min/lunr.vi.min.js delete mode 100644 docs/assets/javascripts/lunr/tinyseg.min.js delete mode 100644 docs/assets/javascripts/vendor.08c56446.min.js delete mode 100644 docs/assets/javascripts/vendor.08c56446.min.js.map delete mode 100644 docs/assets/javascripts/worker/search.8c7e0a7e.min.js delete mode 100644 docs/assets/javascripts/worker/search.8c7e0a7e.min.js.map delete mode 100644 docs/assets/stylesheets/main.3b61ea93.min.css delete mode 100644 docs/assets/stylesheets/main.3b61ea93.min.css.map delete mode 100644 docs/assets/stylesheets/palette.39b8e14a.min.css delete mode 100644 docs/assets/stylesheets/palette.39b8e14a.min.css.map rename {docs_src => docs}/dotNET/ASPdotNET.md (92%) delete mode 100644 docs/dotNET/ASPdotNET/index.html rename {docs_src => docs}/dotNET/AkkadotNET.md (65%) delete mode 100644 docs/dotNET/AkkadotNET/index.html rename {docs_src => docs}/dotNET/C#.md (95%) delete mode 100644 docs/dotNET/C#/index.html rename {docs_src => docs}/dotNET/Multithreading.md (100%) delete mode 100644 docs/dotNET/Multithreading/index.html rename {docs_src => docs}/dotNET/WPF.md (80%) delete mode 100644 docs/dotNET/WPF/index.html delete mode 100644 docs/index.html rename {docs_src => docs}/index.md (86%) delete mode 100644 docs/sitemap.xml delete mode 100644 docs/sitemap.xml.gz delete mode 100644 docs_src/Big_Data/Spark_Development_with_sbt_and_InteliJ.md delete mode 100644 docs_src/Java/Java.md delete mode 100644 docs_src/Linux/Virtualization.md delete mode 100644 docs_src/Markup_and_Documentation/reStructuredText.md diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..a2107a2 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,90 @@ +# syntax=docker/dockerfile:1 + +# Dockerfile reference guide at +# https://docs.docker.com/go/dockerfile-reference/ + +ARG WORK_DIR="/code" + +ARG PYTHON_VERSION=3.12 +FROM python:${PYTHON_VERSION}-slim as base + +# Prevents Python from writing pyc files. +ENV PYTHONDONTWRITEBYTECODE=1 + +# Keeps Python from buffering stdout and stderr to avoid situations where +# the application crashes without emitting any logs due to buffering. +ENV PYTHONUNBUFFERED=1 + +RUN pip install mkdocs +RUN pip install mkdocs-material +## https://github.com/byrnereese/mkdocs-minify-plugin +#RUN pip install mkdocs-minify-plugin +## https://github.com/mkdocs/mkdocs-redirects +#RUN pip install mkdocs-redirects + +ARG WORK_DIR +WORKDIR $WORK_DIR + + +## ------------------------------------------------------------- +FROM base AS dev + +# Install additional OS packages. +# Install pix +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends git pipx + +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Create a non-privileged user +# See https://docs.docker.com/go/dockerfile-user-best-practices/ +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ + # Add sudo support. Omit if you don't need to install software after connecting. + && apt-get update \ + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +# Switch to the non-privileged user. +USER $USERNAME + +# Create aliases +RUN <> $HOME/.bashrc + echo 'alias la="ls -A"' >> $HOME/.bashrc + echo 'alias l="ls -CF"' >> $HOME/.bashrc +EOF + +# # Install Poetry +# # Change some Poetry settings to better deal with working in a container +# ARG WORK_DIR +# RUN --mount=type=cache,target=${WORK_DIR}/.cache \ +# pipx install poetry \ +# && pipx ensurepath + +# Expose the port that the application listens on. +#EXPOSE 8000 + +CMD while sleep 1000; do :; done + +## Run if necessary: +# poetry self update \ +# && poetry config cache-dir "${WORK_DIR}/.cache" \ +# && poetry config virtualenvs.in-project true \ +# && poetry completions bash >> ~/.bash_completion \ +# && poetry install + +## ------------------------------------------------------------- +FROM base AS ci + +# Copy the source code into the container. +COPY . . + +ARG WORK_DIR +RUN rm -rf $WORK_DIR/site/ && mkdocs build + +#CMD [ "ci.sh" ] diff --git a/.devcontainer/compose-ci.yaml b/.devcontainer/compose-ci.yaml new file mode 100644 index 0000000..fe1aea0 --- /dev/null +++ b/.devcontainer/compose-ci.yaml @@ -0,0 +1,8 @@ +name: cheatsheets_ci +services: + site: + build: + target: ci + # Bind the output folder to a folder in the CI host + volumes: + - ../site:/code/site diff --git a/.devcontainer/compose.override.yaml b/.devcontainer/compose.override.yaml new file mode 100644 index 0000000..552d550 --- /dev/null +++ b/.devcontainer/compose.override.yaml @@ -0,0 +1,14 @@ +name: cheatsheets_dev +services: + site: + build: + target: dev + ports: + - 8000:8000 + volumes: + # Update this to wherever you want VS Code to mount the folder of your project + - ..:/code:cached + - /var/run/docker.sock:/var/run/docker-host.sock + + # Overrides default command so things don't shut down after the process ends. + #command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml new file mode 100644 index 0000000..b1ee57b --- /dev/null +++ b/.devcontainer/compose.yaml @@ -0,0 +1,14 @@ +version: '3.8' + +# Docker Compose reference guide at +# https://docs.docker.com/go/compose-spec-reference/ +#For examples, see the Awesome Compose repository: +# https://github.com/docker/awesome-compose +# Note that the path of the Dockerfile and context is relative to the *primary* +# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile" +# array). +services: + site: + build: + context: .. + dockerfile: .devcontainer/Dockerfile diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..175c090 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,60 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose +{ + "name": "Docker Compose", + + // Update the 'dockerComposeFile' list if you have more compose files or use different names. + // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make. + "dockerComposeFile": [ + "compose.yaml", + "compose.override.yaml" + ], + + // The 'service' property is the name of the service for the container that VS Code should + // use. Update this value and .devcontainer/compose.yaml to the real service name. + "service": "site", + + // The optional 'workspaceFolder' property is the path VS Code should open by default when + // connected. This is typically a file mount in .devcontainer/docker-compose.yml + "workspaceFolder": "/code", // "/workspaces/${localWorkspaceFolderBasename}", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "moby": true, + "installDockerBuildx": true, + "version": "latest", + "dockerDashComposeVersion": "v2" + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8000], + + // Uncomment the next line if you want start specific services in your Docker Compose config. + // "runServices": [], + + // Uncomment the next line if you want to keep your containers running after VS Code shuts down. + // "shutdownAction": "none", + + // Uncomment the next line to run commands after the container is created. + // "postCreateCommand": "cat /etc/os-release", + + // Configure tool-specific properties. + // "customizations": {}, + "customizations": { + "vscode": { + "extensions": [ + // "ms-python.vscode-pylance", + // "ms-python.python", + // "ms-python.debugpy", + "DavidAnson.vscode-markdownlint", + "redhat.vscode-yaml" + ] + } + } + + // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "devcontainer" +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4f17fb0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,35 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +site/ +**/.DS_Store +**/__pycache__ +**/.venv +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/bin +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/.gitattributes b/.gitattributes index bdb0cab..7dd180c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,17 +1,129 @@ # Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain +* text=auto eol=lf + +## ----------------------------------------------------- + +# Basic .gitattributes for a python repo. + +# Source files +# ============ +*.pxd text diff=python +*.py text diff=python +*.py3 text diff=python +*.pyw text diff=python +*.pyx text diff=python +*.pyz text diff=python +*.pyi text diff=python + +# Binary files +# ============ +*.db binary +*.p binary +*.pkl binary +*.pickle binary +*.pyc binary export-ignore +*.pyo binary export-ignore +*.pyd binary + +# Jupyter notebook +*.ipynb text eol=lf + +# Note: .db, .p, and .pkl files are associated +# with the python modules ``pickle``, ``dbm.*``, +# ``shelve``, ``marshal``, ``anydbm``, & ``bsddb`` +# (among others). + +## ----------------------------------------------------- + +# Fix syntax highlighting on GitHub to allow comments +.devcontainer.json linguist-language=JSON-with-Comments +devcontainer.json linguist-language=JSON-with-Comments + +## ----------------------------------------------------- + +# Fix syntax highlighting on GitHub to allow comments +.vscode/*.json linguist-language=JSON-with-Comments + +## ----------------------------------------------------- + +# Common settings that generally should always be used with your language specific settings + +# +# The above will handle all files NOT found below +# + +# Documents +*.bibtex text diff=bibtex +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text diff=markdown +*.mdx text diff=markdown +*.tex text diff=tex +*.adoc text +*.textile text +*.mustache text +*.csv text eol=crlf +*.tab text +*.tsv text +*.txt text +*.sql text +*.epub diff=astextplain + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as text by default. +*.svg text +# If you want to treat it as binary, +# use the following line instead. +# *.svg binary +*.eps binary + +# Scripts +*.bash text eol=lf +*.fish text eol=lf +*.ksh text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +# These are explicitly windows files and should use crlf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +# Serialisation +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# Archives +*.7z binary +*.gz binary +*.tar binary +*.tgz binary +*.zip binary + +# Text files where line endings should be preserved +*.patch -text + +# +# Exclude files from exporting +# + +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..1a481eb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: monthly diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..92f7440 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,29 @@ +name: ci +on: + push: + branches: + - master + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + - uses: actions/setup-python@v5 + with: + python-version: 3.12 + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v4 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore index 269c9d3..ae79f66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,23 @@ +.cache/ +site/ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ +## VS Code ----------------------------------------------- -# Locally stored "Eclipse launch configurations" -*.launch +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets -# CDT-specific -.cproject - -# PDT-specific -.buildpath +# Local History for Visual Studio Code +.history/ +# Built Visual Studio Code Extensions +*.vsix ################# -## Visual Studio +## Visual Studio ------------------------------------------ ################# ## Ignore Visual Studio temporary files, build results, and @@ -168,25 +154,7 @@ App_Data/*.mdf App_Data/*.ldf ############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python +## Python ------------------------------------------ ############# *.py[cod] @@ -215,3 +183,212 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +############# +## Windows detritus ------------------------------------------------------- +############# + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +## Mac / Linux ------------------------------------ + +# Mac +.DS_Store + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..57e7e14 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.enabled": true +} diff --git a/README.md b/README.md index 23dba56..d56e898 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,53 @@ +# Cheatsheets -[John's Cheatsheets](http://john-cd.com/cheatsheets/) +[John's Cheatsheets](https://john-cd.com/cheatsheets/) -[John's Main Website](http://john-cd.com) +[John's Main Website](https://john-cd.com) -This website is generated by [MkDocs](http://mkdocs.org). +This website is generated by [MkDocs](https://mkdocs.org). + +## Basic MkDocs Commands + +- ``mkdocs new [dir-name]`` - Create a new project. +- ``mkdocs serve`` - Start the live-reloading docs server. +- ``mkdocs build`` - Build the documentation site. +- ``mkdocs help`` - Print this help message. + +The source Markdown files are found in the `docs` folder. + +Within Dev Containers, use `mkdocs serve --dev-addr 0.0.0.00:8000` ## Install -With Python 3.8 installed on Windows globally: +### Manual install + +Install `Python`, then: ```shell python -m pip install mkdocs --user python -m pip install mkdocs-material --user ``` -## Basic MkDocs Commands +### Building with Docker Compose -- ``mkdocs new [dir-name]`` - Create a new project. -- ``mkdocs serve`` - Start the live-reloading docs server. -- ``mkdocs build`` - Build the documentation site. -- ``mkdocs help`` - Print this help message. +Start by running: `docker compose up --build`. + +Your application will be available at . + +### Deploying + +First, build your image, e.g.: `docker build -t myapp .`. + +If your cloud uses a different CPU architecture than your development +machine (e.g., you are on a Mac M1 and your cloud provider is amd64), +you'll want to build the image for that platform, e.g.: +`docker build --platform=linux/amd64 -t myapp .`. + +Then, push it to your registry, e.g. `docker push myregistry.com/myapp`. + +Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/) +docs for more detail on building and pushing. + +### References -The source Markdown files are found in the ``docs_src`` folder. +[Docker's Python guide](https://docs.docker.com/language/python/) diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index 962b143..0000000 --- a/docs/404.html +++ /dev/null @@ -1,1839 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
- -

404 - Not found

- - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Hadoop_Ecosystem.md b/docs/Big_Data/Hadoop_Ecosystem.md similarity index 62% rename from docs_src/Big_Data/Hadoop_Ecosystem.md rename to docs/Big_Data/Hadoop_Ecosystem.md index 9bd4dde..7036a14 100644 --- a/docs_src/Big_Data/Hadoop_Ecosystem.md +++ b/docs/Big_Data/Hadoop_Ecosystem.md @@ -1,27 +1,25 @@ # Hadoop Ecosystem Hadoop is not a single product, but rather a software family. Its common components consist of the following: - -- Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources -- Hive, used to facilitate structure for the data -- HCatalog, used to provide inter-operatability between these internal systems -- HBase, which is essentially a database built on top of Hadoop + +- Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources +- Hive, used to facilitate structure for the data +- HCatalog, used to provide inter-operatability between these internal systems +- HBase, which is essentially a database built on top of Hadoop - HDFS, the actual file system for hadoop. - Apache Mahout -- Packaging for Hadoop: [BigTop]( http://bigtop.apache.org/ ) +- Packaging for Hadoop: [BigTop]( https://bigtop.apache.org/ ) Hadoop structures data using Hive, but can handle unstructured data easily using Pig. - ## Hadoop and Mongo - [Hadoop and MongoDB]( https://www.mongodb.com/hadoop-and-mongodb?_ga=1.104126339.207014561.1422350149 ) -- [Hadoop and MongoDB Use Cases]( http://docs.mongodb.org/ecosystem/use-cases/hadoop/ ) - +- [Hadoop and MongoDB Use Cases]( https://docs.mongodb.org/ecosystem/use-cases/hadoop/ ) ## AWS EMR -[Amazon EMR Best Practices]( http://media.amazonwebservices.com/AWS_Amazon_EMR_Best_Practices.pdf ) +[Amazon EMR Best Practices]( https://media.amazonwebservices.com/AWS_Amazon_EMR_Best_Practices.pdf ) Amazon EMR includes @@ -41,4 +39,3 @@ Amazon EMR includes - Tez - Zeppelin - ZooKeeper - diff --git a/docs/Big_Data/Hadoop_Ecosystem/index.html b/docs/Big_Data/Hadoop_Ecosystem/index.html deleted file mode 100644 index 67e1519..0000000 --- a/docs/Big_Data/Hadoop_Ecosystem/index.html +++ /dev/null @@ -1,2010 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Hadoop Ecosystem - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Hadoop Ecosystem

-

Hadoop is not a single product, but rather a software family. Its common components consist of the following:

-
    -
  • Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources
  • -
  • Hive, used to facilitate structure for the data
  • -
  • HCatalog, used to provide inter-operatability between these internal systems
  • -
  • HBase, which is essentially a database built on top of Hadoop
  • -
  • HDFS, the actual file system for hadoop.
  • -
  • Apache Mahout
  • -
  • Packaging for Hadoop: BigTop
  • -
-

Hadoop structures data using Hive, but can handle unstructured data easily using Pig.

-

Hadoop and Mongo

- -

AWS EMR

-

Amazon EMR Best Practices

-

Amazon EMR includes

-
    -
  • Ganglia
  • -
  • Hadoop
  • -
  • HBase
  • -
  • HCatalog
  • -
  • Hive
  • -
  • Hue
  • -
  • Mahout
  • -
  • Oozie
  • -
  • Phoenix
  • -
  • Pig
  • -
  • Prest0
  • -
  • Spark
  • -
  • Sqoop
  • -
  • Tez
  • -
  • Zeppelin
  • -
  • ZooKeeper
  • -
- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Install_Spark_2.3_Locally.md b/docs/Big_Data/Install_Spark_2.3_Locally.md similarity index 93% rename from docs_src/Big_Data/Install_Spark_2.3_Locally.md rename to docs/Big_Data/Install_Spark_2.3_Locally.md index b97fe9f..3813467 100644 --- a/docs_src/Big_Data/Install_Spark_2.3_Locally.md +++ b/docs/Big_Data/Install_Spark_2.3_Locally.md @@ -1,25 +1,24 @@ # Install Spark 2.3 Locally -Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11. +Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11. ## Download Spark -[ Link ]( https://spark.apache.org/downloads.html ) - +[Link]( https://spark.apache.org/downloads.html ) ## Java All you need is to have java installed on your system PATH, or the JAVA_HOME environment variable pointing to a Java installation. ```shell -java -version +java -version ``` ## Scala Download the Scala binaries for windows -- you will need Scala 11.x (not 10.x or 12.x) for Spark 2.3 -- [Latest Scala]( http://www.scala-lang.org/download/ ) +- [Latest Scala]( https://www.scala-lang.org/download/ ) - [Scala version 2.11.12]( https://www.scala-lang.org/download/2.11.12.html ) Test correct installation of scala: @@ -42,13 +41,11 @@ Test that Spark is properly installed: On Windows, use CMD or PowerShell, not git bash - ## Error: Failure to locate the winutils binary in the hadoop binary path - HADOOP_HOME (or the variable hadoop.home.dir property) needs to be set properly. - Known Hadoop for Windows issue: winutils is not included in the Apache distribution - You can fix this problem in two ways - Install a full native windows Hadoop version. The ASF does not currently release such a version; releases are available externally. @@ -59,14 +56,12 @@ Then - Set the environment variable %HADOOP_HOME% to point to the directory above the BIN dir containing WINUTILS.EXE. - Or: run the Java process with the system property hadoop.home.dir set to the home directory. - [Explanation on Hadoop Wiki]( https://wiki.apache.org/hadoop/WindowsProblems ) [Stack Overflow]( https://stackoverflow.com/questions/19620642/failed-to-locate-the-winutils-binary-in-the-hadoop-binary-path?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa ) [Windows binaries for some Hadoop versions]( https://github.com/steveloughran/winutils ) - ## Run Spark on the local machine To run Spark interactively in a Python interpreter, use ``bin/pyspark``: @@ -81,8 +76,6 @@ Or submit Spark jobs: ./bin/spark-submit examples/src/main/python/pi.py 10 ``` - ## Additional Links [Spark Installation Tutorial]( https://www.tutorialspoint.com/apache_spark/apache_spark_installation.htm ) - diff --git a/docs/Big_Data/Install_Spark_2.3_Locally/index.html b/docs/Big_Data/Install_Spark_2.3_Locally/index.html deleted file mode 100644 index 09eddf6..0000000 --- a/docs/Big_Data/Install_Spark_2.3_Locally/index.html +++ /dev/null @@ -1,2085 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Install Spark 2.3 Locally - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Install Spark 2.3 Locally

-

Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11.

-

Download Spark

-

Link

-

Java

-

All you need is to have java installed on your system PATH, or the JAVA_HOME environment variable pointing to a Java installation.

-
java -version 
-
- -

Scala

-

Download the Scala binaries for windows -- you will need Scala 11.x (not 10.x or 12.x) for Spark 2.3

- -

Test correct installation of scala:

-
scala -version
-
- -

Set PATH for Scala if needed:

-
export PATH = $PATH:/usr/local/scala/bin
-
- -

Test that Spark is properly installed:

-
./bin/spark-shell --master local[2]
-
- -

On Windows, use CMD or PowerShell, not git bash

-

Error: Failure to locate the winutils binary in the hadoop binary path

-
    -
  • HADOOP_HOME (or the variable hadoop.home.dir property) needs to be set properly.
  • -
  • Known Hadoop for Windows issue: winutils is not included in the Apache distribution
  • -
-

You can fix this problem in two ways

-
    -
  • Install a full native windows Hadoop version. The ASF does not currently release such a version; releases are available externally. -Or: get the WINUTILS.EXE binary from a Hadoop redistribution. There is a repository of this for some Hadoop versions on github.
  • -
-

Then

-
    -
  • Set the environment variable %HADOOP_HOME% to point to the directory above the BIN dir containing WINUTILS.EXE.
  • -
  • Or: run the Java process with the system property hadoop.home.dir set to the home directory.
  • -
-

Explanation on Hadoop Wiki

-

Stack Overflow

-

Windows binaries for some Hadoop versions

-

Run Spark on the local machine

-

To run Spark interactively in a Python interpreter, use bin/pyspark:

-
./bin/pyspark --master local[2]
-
- -

Or submit Spark jobs:

-
./bin/spark-submit examples/src/main/python/pi.py 10
-
- - -

Spark Installation Tutorial

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Spark_APIs.md b/docs/Big_Data/Spark_APIs.md similarity index 81% rename from docs_src/Big_Data/Spark_APIs.md rename to docs/Big_Data/Spark_APIs.md index dc1f428..aaffe8c 100644 --- a/docs_src/Big_Data/Spark_APIs.md +++ b/docs/Big_Data/Spark_APIs.md @@ -1,8 +1,6 @@ - - ## DataFrames APIs -DataFrame operations: +DataFrame operations: - printSchema() - select() @@ -40,13 +38,13 @@ df.groupBy("project").sum().show() A new column is constructed based on the input columns present in a dataframe: ```scala -df("columnName") // On a specific DataFrame. -col("columnName") // A generic column no yet associated with a DataFrame. -col("columnName.field") // Extracting a struct field +df("columnName") // On a specific DataFrame. +col("columnName") // A generic column no yet associated with a DataFrame. +col("columnName.field") // Extracting a struct field col("`a.column.with.dots`") // Escape `.` in column names. -$"columnName" // Scala short hand for a named column. -expr("a + 1") // A column that is constructed from a parsed SQL Expression. -lit("abc") // A column that produces a literal (constant) value. +$"columnName" // Scala short hand for a named column. +expr("a + 1") // A column that is constructed from a parsed SQL Expression. +lit("abc") // A column that produces a literal (constant) value. ``` Column objects can be composed to form complex expressions: @@ -68,7 +66,7 @@ val clickstreamDF = sqlContext.read.format("com.databricks.spark.csv") .option("inferSchema", "true") .load("dbfs:///databricks-datasets/wikipedia-datasets/data-001/clickstream/raw-uncompressed") ``` - + PARQUET - To create Dataset[Row] using SparkSession ```scala diff --git a/docs/Big_Data/Spark_APIs/index.html b/docs/Big_Data/Spark_APIs/index.html deleted file mode 100644 index 9424018..0000000 --- a/docs/Big_Data/Spark_APIs/index.html +++ /dev/null @@ -1,2084 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Spark APIs - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Spark APIs

- -

DataFrames APIs

-

DataFrame operations:

-
    -
  • printSchema()
  • -
  • select()
  • -
  • show()
  • -
  • count()
  • -
  • groupBy()
  • -
  • sum()
  • -
  • limit()
  • -
  • orderBy()
  • -
  • filter()
  • -
  • withColumnRenamed()
  • -
  • join()
  • -
  • withColumn()
  • -
-

Example:

-
// In the Regular Expression below:
-// ^  - Matches beginning of line
-// .* - Matches any characters, except newline
-
-df
- .filter($"article".rlike("""^Apache_.*"""))
- .orderBy($"requests".desc)
- .show() // By default, show will return 20 rows
-
-// Import the sql functions package, which includes statistical functions like sum, max, min, avg, etc.
-import org.apache.spark.sql.functions._
-
-df.groupBy("project").sum().show()
-
- -

Columns

-

A new column is constructed based on the input columns present in a dataframe:

-
df("columnName")            // On a specific DataFrame.
-col("columnName")           // A generic column no yet associated with a DataFrame.
-col("columnName.field")     // Extracting a struct field
-col("`a.column.with.dots`") // Escape `.` in column names.
-$"columnName"               // Scala short hand for a named column.
-expr("a + 1")               // A column that is constructed from a parsed SQL Expression.
-lit("abc")                  // A column that produces a literal (constant) value.
-
- -

Column objects can be composed to form complex expressions:

-
$"a" + 1
-$"a" === $"b"
-
- -

File Read

-

CSV - Create a DataFrame with the anticipated structure

-
val clickstreamDF = sqlContext.read.format("com.databricks.spark.csv")
-  .option("header", "true")
-  .option("delimiter", "\\t")
-  .option("mode", "PERMISSIVE")
-  .option("inferSchema", "true")
-  .load("dbfs:///databricks-datasets/wikipedia-datasets/data-001/clickstream/raw-uncompressed")
-
- -

PARQUET - To create Dataset[Row] using SparkSession

-
val people = spark.read.parquet("...")
-val department = spark.read.parquet("...")
-
-people.filter("age > 30")
-  .join(department, people("deptId") === department("id"))
-  .groupBy(department("name"), "gender")
-  .agg(avg(people("salary")), max(people("age")))
-
- -

Repartitioning / Caching

-
val clickstreamNoIDs8partDF = clickstreamNoIDsDF.repartition(8)
-clickstreamNoIDs8partDF.registerTempTable("Clickstream")
-sqlContext.cacheTable("Clickstream")
-
- -

An ideal partition size in Spark is about 50 MB - 200 MB. -The cache gets stored in Project Tungsten binary compressed columnar format.

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Spark_Basics.md b/docs/Big_Data/Spark_Basics.md similarity index 85% rename from docs_src/Big_Data/Spark_Basics.md rename to docs/Big_Data/Spark_Basics.md index 774e57d..6b8bc40 100644 --- a/docs_src/Big_Data/Spark_Basics.md +++ b/docs/Big_Data/Spark_Basics.md @@ -1,20 +1,19 @@ # Spark Basics -- [Main Web Site]( http://spark.apache.org/ ) -- [Apache Spark on Wikipedia]( http://en.wikipedia.org/wiki/Apache_Spark ) +- [Main Web Site]( https://spark.apache.org/ ) +- [Apache Spark on Wikipedia]( https://en.wikipedia.org/wiki/Apache_Spark ) ## Useful Links -- [Ampcamp big data bootcamp](http://ampcamp.berkeley.edu/) -- [RDDs Simplified]( http://datalakes.com/rdds-simplified/ ) +- [Ampcamp big data bootcamp](https://ampcamp.berkeley.edu/) +- [RDDs Simplified]( https://datalakes.com/rdds-simplified/ ) - [Elasticsearch and Apache Lucene for Apache Spark and MLlib]( https://spark-summit.org/2016/events/elasticsearch-and-apache-lucene-for-apache-spark-and-mllib/ ) - [Spark on AWS]( https://aws.amazon.com/emr/details/spark/ ) - [Running Apache Spark on AWS]( https://www.getblueshift.com/running-apache-spark-1-0-on-aws/ ) - [Running Apache Spark EMR and EC2 scripts on AWS with read write S3]( https://bigsnarf.wordpress.com/2015/01/21/running-apache-spark-emr-on-aws/ ) - [Spark on EMR - How to Submit a Spark Application with EMR Steps]( https://github.com/awslabs/emr-bootstrap-actions/blob/master/spark/examples/spark-submit-via-step.md ) - [Databricks Reference Apps]( https://www.gitbook.com/book/databricks/databricks-spark-reference-applications/details ) -- [Introduction to Apache Spark with Examples and Use Cases]( http://www.hadoop360.com/blog/introduction-to-apache-spark-with-examples-and-use-cases ) - +- [Introduction to Apache Spark with Examples and Use Cases]( https://www.hadoop360.com/blog/introduction-to-apache-spark-with-examples-and-use-cases ) ## Spark and MongoDB @@ -37,10 +36,8 @@ and in the following project the use of CTAKES UIMA module from within the Spark - [Graphx programming guide]( https://spark.apache.org/docs/latest/graphx-programming-guide.html ) - ## Apache Zeppelin Connect to Zeppelin using the same SSH tunneling method to connect to other web servers on the master node. Zeppelin server is found at port 8890. [Zeppelin]( https://zeppelin.incubator.apache.org ) - diff --git a/docs/Big_Data/Spark_Basics/index.html b/docs/Big_Data/Spark_Basics/index.html deleted file mode 100644 index 94e410e..0000000 --- a/docs/Big_Data/Spark_Basics/index.html +++ /dev/null @@ -1,2051 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Spark Basics - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Spark Basics

- - - -

Spark and MongoDB

- -

Spark and NLP

- -

Here is a complete set of example on how to use DL4J (Deep Learning for Java) that uses UIMA on the SPARK platform

-

Deep Learning for Java

-

and in the following project the use of CTAKES UIMA module from within the Spark framework

-

Natural Language Processing with Apache Spark

-

GraphX

- -

Apache Zeppelin

-

Connect to Zeppelin using the same SSH tunneling method to connect to other web servers on the master node. Zeppelin server is found at port 8890.

-

Zeppelin

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ.md b/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ.md new file mode 100644 index 0000000..e7cc8e9 --- /dev/null +++ b/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ.md @@ -0,0 +1,46 @@ +# Setup a Spark Development Environment with IntelliJ and sbt + +## Useful Links + +[Hortonworks tutorial]( https://hortonworks.com/tutorial/setting-up-a-spark-development-environment-with-scala/ ) + +## Packaging and Submission Steps using sbt + +Package a jar containing your application: + +```shell +$ sbt package +... +[info] Packaging {..}/{..}/target/scala-2.11/simple-project_2.11-1.0.jar +``` + +Don't use ``sbt run`` + +Then use [spark submit] ( ) + to run your application + +```sh +YOUR_SPARK_HOME/bin/spark-submit \ + --class "SimpleApp" \ + --master local[4] \ + target/scala-2.11/simple-project_2.11-1.0.jar +``` + +Open the Spark UI to monitor: [https://localhost:4040]( https://localhost:4040 ) + +## Plugins + +### sbt-spark-package + +The [Sbt Plugin for Spark Packages]( https://github.com/databricks/sbt-spark-package ) is a Sbt plugin that aims to simplify the use and development of Spark Packages. + +[Blog]( https://medium.com/@mrpowers/creating-a-spark-project-with-sbt-intellij-sbt-spark-package-and-friends-cc9108751c28 ) + +### IntelliJ plugin for Spark + +Note: does not work with IntelliJ 2018.1 + +The [IntelliJ plugin for Spark]( https://plugins.jetbrains.com/plugin/10412-spark ) supports for deployment spark application and cluster monitoring. + +- To install, download the plugin +- File > Settings, Plugins tab, browse repos... point to the zip file diff --git a/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html b/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html deleted file mode 100644 index 525785a..0000000 --- a/docs/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html +++ /dev/null @@ -1,2057 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Setup a Spark Development Environment with IntelliJ and sbt - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Setup a Spark Development Environment with IntelliJ and sbt

- -

Hortonworks tutorial

-

Packaging and Submission Steps using sbt

-

Package a jar containing your application:

-
$ sbt package
-...
-[info] Packaging {..}/{..}/target/scala-2.11/simple-project_2.11-1.0.jar
-
- -

Don't use sbt run

-

Then use [spark submit] ( https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit ) - to run your application

-
YOUR_SPARK_HOME/bin/spark-submit \
-  --class "SimpleApp" \
-  --master local[4] \
-  target/scala-2.11/simple-project_2.11-1.0.jar
-
- -

Open the Spark UI to monitor: http://localhost:4040

-

Plugins

-

sbt-spark-package

-

The Sbt Plugin for Spark Packages is a Sbt plugin that aims to simplify the use and development of Spark Packages.

-

Blog

-

IntelliJ plugin for Spark

-

Note: does not work with IntelliJ 2018.1

-

The IntelliJ plugin for Spark supports for deployment spark application and cluster monitoring.

-
    -
  • To install, download the plugin
  • -
  • File > Settings, Plugins tab, browse repos... point to the zip file
  • -
- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Spark_on_AWS_EMR.md b/docs/Big_Data/Spark_on_AWS_EMR.md similarity index 71% rename from docs_src/Big_Data/Spark_on_AWS_EMR.md rename to docs/Big_Data/Spark_on_AWS_EMR.md index 597be7a..0654c25 100644 --- a/docs_src/Big_Data/Spark_on_AWS_EMR.md +++ b/docs/Big_Data/Spark_on_AWS_EMR.md @@ -2,7 +2,7 @@ ## Key Links -[Spark on AWS EMR](http://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark.html ) +[Spark on AWS EMR](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark.html ) ## Create a EMR Cluster with Spark using the AWS Console @@ -10,23 +10,22 @@ The following procedure creates a cluster with Spark installed. 1. Open the Amazon EMR console at [https://console.aws.amazon.com/elasticmapreduce/]( https://console.aws.amazon.com/elasticmapreduce/ ). 1. Choose Create cluster to use Quick Create. - 1. For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later. - 1. In the Select Applications field, choose either All Applications or Spark. - 1. Select other options as necessary and then choose Create cluster - + + - For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later. + - In the Select Applications field, choose either All Applications or Spark. + - Select other options as necessary and then choose Create cluster ## Create a EMR Cluster with Spark using the AWS CLI *Simple cluster:* ```bash -aws emr create-cluster --name "Spark cluster" --release-label emr-5.0.0 --applications Name=Spark \ +aws emr create-cluster --name "Spark cluster" --release-label emr-5.0.0 --applications Name=Spark \ --ec2-attributes KeyName=myKey --instance-type m3.xlarge --instance-count 3 --use-default-roles ``` Note: For Windows, replace the above Linux line continuation character (\) with the caret (^). - *When using a config file:* ```bash @@ -91,17 +90,16 @@ The output lists your clusters including the cluster IDs. Note the cluster ID fo aws emr list-instances --cluster-id j-2AL4XXXXXX5T9Or:aws emr describe-clusters --cluster-id j-2AL4XXXXXX5T9 ``` - ## View the Web Interfaces Hosted on Amazon EMR Clusters -- [View Web Interfaces Hosted on Amazon EMR Clusters]( http://docs.aws.amazon.com//ElasticMapReduce/latest/ManagementGuide/emr-web-interfaces.html ) - -- YARN ResourceManager: [http://master-public-dns-name:8088]( http://master-public-dns-name:8088/ ) -- YARN NodeManager: [http://slave-public-dns-name:8042]( http://slave-public-dns-name:8042/ ) -- Hadoop HDFS NameNode: [http://master-public-dns-name:50070]( http://master-public-dns-name:50070/ ) -- Hadoop HDFS DataNode: [http://slave-public-dns-name:50075]( http://slave-public-dns-name:50075/ ) -- Spark HistoryServer: [http://master-public-dns-name:18080]( http://master-public-dns-name:18080/ ) -- Zeppelin: [http://master-public-dns-name:8890]( http://master-public-dns-name:8890/ ) -- Hue: [http://master-public-dns-name:8888]( http://master-public-dns-name:8888/ ) -- Ganglia: [http://master-public-dns-name/ganglia]( http://master-public-dns-name/ganglia/ ) -- HBase UI: [http://master-public-dns-name:16010]( http://master-public-dns-name:16010/ ) +- [View Web Interfaces Hosted on Amazon EMR Clusters]( https://docs.aws.amazon.com//ElasticMapReduce/latest/ManagementGuide/emr-web-interfaces.html ) + +- YARN ResourceManager: [https://master-public-dns-name:8088]( https://master-public-dns-name:8088/ ) +- YARN NodeManager: [https://slave-public-dns-name:8042]( https://slave-public-dns-name:8042/ ) +- Hadoop HDFS NameNode: [https://master-public-dns-name:50070]( https://master-public-dns-name:50070/ ) +- Hadoop HDFS DataNode: [https://slave-public-dns-name:50075]( https://slave-public-dns-name:50075/ ) +- Spark HistoryServer: [https://master-public-dns-name:18080]( https://master-public-dns-name:18080/ ) +- Zeppelin: [https://master-public-dns-name:8890]( https://master-public-dns-name:8890/ ) +- Hue: [https://master-public-dns-name:8888]( https://master-public-dns-name:8888/ ) +- Ganglia: [https://master-public-dns-name/ganglia]( https://master-public-dns-name/ganglia/ ) +- HBase UI: [https://master-public-dns-name:16010]( https://master-public-dns-name:16010/ ) diff --git a/docs/Big_Data/Spark_on_AWS_EMR/index.html b/docs/Big_Data/Spark_on_AWS_EMR/index.html deleted file mode 100644 index 636f5c2..0000000 --- a/docs/Big_Data/Spark_on_AWS_EMR/index.html +++ /dev/null @@ -1,2104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Spark on AWS EMR - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Spark on AWS EMR

- -

Spark on AWS EMR

-

Create a EMR Cluster with Spark using the AWS Console

-

The following procedure creates a cluster with Spark installed.

-
    -
  1. Open the Amazon EMR console at https://console.aws.amazon.com/elasticmapreduce/.
  2. -
  3. Choose Create cluster to use Quick Create.
      -
    1. For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later.
    2. -
    3. In the Select Applications field, choose either All Applications or Spark.
    4. -
    5. Select other options as necessary and then choose Create cluster
    6. -
    -
  4. -
-

Create a EMR Cluster with Spark using the AWS CLI

-

Simple cluster:

-
aws emr create-cluster --name "Spark cluster" --release-label emr-5.0.0 --applications Name=Spark \ 
---ec2-attributes KeyName=myKey --instance-type m3.xlarge --instance-count 3 --use-default-roles
-
- -

Note: For Windows, replace the above Linux line continuation character () with the caret (^).

-

When using a config file:

-
aws emr create-cluster --release-label --applications Name=Spark \
---instance-type m3.xlarge --instance-count 3 --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json
-
- -

Sample myConfig.json:

-
[
-  {
-    "Classification": "spark",
-    "Properties": {
-      "maximizeResourceAllocation": "true"
-    }
-  }
-]
-
- -

Using Spot instances:

-
aws emr create-cluster --name "Spot cluster" --release-label emr-5.0.0 --applications Name=Spark \
---use-default-roles --ec2-attributes KeyName=myKey \
---instance-groups InstanceGroupType=MASTER,InstanceType=m3.xlarge,InstanceCount=1,BidPrice=0.25 \
-InstanceGroupType=CORE,BidPrice=0.03,InstanceType=m3.xlarge,InstanceCount=2
-
-# InstanceGroupType=TASK,BidPrice=0.10,InstanceType=m3.xlarge,InstanceCount=3
-
- -

In Java:

-
// start Spark on EMR in java
-AmazonElasticMapReduceClient emr = new AmazonElasticMapReduceClient(credentials);
-Application sparkApp = new Application() .withName("Spark");
-Applications myApps = new Applications();
-myApps.add(sparkApp);
-RunJobFlowRequest request = new RunJobFlowRequest() .withName("Spark Cluster") .withApplications(myApps) .withReleaseLabel("") .withInstances(new JobFlowInstancesConfig() .withEc2KeyName("myKeyName") .withInstanceCount(1) .withKeepJobFlowAliveWhenNoSteps(true) .withMasterInstanceType("m3.xlarge") .withSlaveInstanceType("m3.xlarge") ); RunJobFlowResult result = emr.runJobFlow(request);
-
- -

Connect to the Master Node using SSH

-

To connect to the master node using SSH, you need the public DNS name of the master node and your Amazon EC2 key pair private key. The Amazon EC2 key pair private key is specified when you launch the cluster.

-
    -
  1. To retrieve the cluster identifier / the public DNS name of the master node, type the following command:
  2. -
-
aws emr list-clusters
-
- -

The output lists your clusters including the cluster IDs. Note the cluster ID for the cluster to which you are connecting.

-
"Status": {     "Timeline": {         "ReadyDateTime": 1408040782.374,         "CreationDateTime": 1408040501.213     },     "State": "WAITING",     "StateChangeReason": {         "Message": "Waiting after step completed"     } }, "NormalizedInstanceHours": 4,"Id": "j-2AL4XXXXXX5T9", "Name": "My cluster"
-
- -
    -
  1. To list the cluster instances including the master public DNS name for the cluster, type one of the following commands. Replace j-2AL4XXXXXX5T9 with the cluster ID returned by the previous command.
  2. -
-
aws emr list-instances --cluster-id j-2AL4XXXXXX5T9Or:aws emr describe-clusters --cluster-id j-2AL4XXXXXX5T9
-
- -

View the Web Interfaces Hosted on Amazon EMR Clusters

- - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Spark_on_EC2.md b/docs/Big_Data/Spark_on_EC2.md similarity index 91% rename from docs_src/Big_Data/Spark_on_EC2.md rename to docs/Big_Data/Spark_on_EC2.md index 872b329..e1403b7 100644 --- a/docs_src/Big_Data/Spark_on_EC2.md +++ b/docs/Big_Data/Spark_on_EC2.md @@ -2,7 +2,7 @@ ## Key Links -[ Flintrock GitHub Repo]( https://github.com/nchammas/flintrock ) +[Flintrock GitHub Repo]( https://github.com/nchammas/flintrock ) ## Configurable CLI Defaults @@ -40,4 +40,4 @@ With a config file like that, you can now launch a cluster: ```shell flintrock launch test-cluster -``` \ No newline at end of file +``` diff --git a/docs/Big_Data/Spark_on_EC2/index.html b/docs/Big_Data/Spark_on_EC2/index.html deleted file mode 100644 index 8b3e87c..0000000 --- a/docs/Big_Data/Spark_on_EC2/index.html +++ /dev/null @@ -1,2018 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Install Spark on EC2 with Flintrock - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Install Spark on EC2 with Flintrock

- -

Flintrock GitHub Repo

-

Configurable CLI Defaults

-

Flintrock lets you persist your desired configuration to a YAML file so that you don't have to keep typing out the same options over and over at the command line.

-

To setup and edit the default config file, run this:

-
flintrock configure
-
- -

Sample config.yaml

-
provider: ec2
-
-services:
-  spark:
-    version: 2.2.0
-
-launch:
-  num-slaves: 1
-
-providers:
-  ec2:
-    key-name: key_name
-    identity-file: /path/to/.ssh/key.pem
-    instance-type: m3.medium
-    region: us-east-1
-    ami: ami-97785bed
-    user: ec2-user
-
- -

With a config file like that, you can now launch a cluster:

-
flintrock launch test-cluster
-
- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Big_Data/Spark_on_Kubernetes.md b/docs/Big_Data/Spark_on_Kubernetes.md similarity index 89% rename from docs_src/Big_Data/Spark_on_Kubernetes.md rename to docs/Big_Data/Spark_on_Kubernetes.md index 30f6b48..ce6d48a 100644 --- a/docs_src/Big_Data/Spark_on_Kubernetes.md +++ b/docs/Big_Data/Spark_on_Kubernetes.md @@ -7,10 +7,9 @@ tags: Kubernetes MiniKube Kubectl Spark [Introduction to Spark on Kubernetes](https://banzaicloud.github.io/blog/spark-k8s/) - ## Running Spark on Kubernetes -[Main Page]( https://spark.apache.org/docs/latest/running-on-kubernetes.html ) +[Main Page]( https://spark.apache.org/docs/latest/running-on-kubernetes.html ) Prerequisites: @@ -22,7 +21,7 @@ We recommend using the latest release of minikube with the DNS addon enabled. The service account credentials used by the driver pods must be allowed to create pods, services and configmaps. - You must have Kubernetes DNS configured in your cluster. -### Steps +### Steps - Need Kubernetes version 1.6 and above. To check the version, enter ``kubectl version``. @@ -35,14 +34,13 @@ minikube addons list [Kubernetes DNS Page]( https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ ) - - Start minikube with the recommended configuration for Spark ```shell minikube start --cpus 3 --memory 4096 ``` -- Submit a Spark job using: +- Submit a Spark job using: ```shell $ bin/spark-submit \ @@ -62,23 +60,22 @@ Spark (starting with version 2.3) ships with a Dockerfile in the ``kubernetes/do - Access logs: ```shell -$ kubectl -n= logs -f +kubectl -n= logs -f ``` - Accessing Driver UI: ```shell -$ kubectl port-forward 4040:4040 +kubectl port-forward 4040:4040 ``` -Then go to [ http://localhost:4040 ]( http://localhost:4040 ) - +Then go to [https://localhost:4040]( https://localhost:4040 ) ## Alternatives [Helm Chart for Spark]( https://github.com/kubernetes/charts/tree/master/stable/spark ) -[The same on KubeApps ]( https://hub.kubeapps.com/charts/stable/spark ) +[The same on KubeApps]( https://hub.kubeapps.com/charts/stable/spark ) ```shell helm install --name my-spark-release --version 0.1.12 stable/spark diff --git a/docs/Big_Data/Spark_on_Kubernetes/index.html b/docs/Big_Data/Spark_on_Kubernetes/index.html deleted file mode 100644 index 735a1bd..0000000 --- a/docs/Big_Data/Spark_on_Kubernetes/index.html +++ /dev/null @@ -1,2077 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Spark 2.3 on Kubernetes - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Spark 2.3 on Kubernetes

- -

Background

-

Introduction to Spark on Kubernetes

-

Running Spark on Kubernetes

-

Main Page

-

Prerequisites:

-
    -
  • A runnable distribution of Spark 2.3 or above.
  • -
  • A running Kubernetes cluster at version >= 1.6 with access configured to it using kubectl. If you do not already have a working Kubernetes cluster, you may setup a test cluster on your local machine using minikube. -We recommend using the latest release of minikube with the DNS addon enabled.
  • -
  • Be aware that the default minikube configuration is not enough for running Spark applications. We recommend 3 CPUs and 4g of memory to be able to start a simple Spark application with a single executor.
  • -
  • You must have appropriate permissions to list, create, edit and delete pods in your cluster. You can verify that you can list these resources by running kubectl auth can-i pods. -The service account credentials used by the driver pods must be allowed to create pods, services and configmaps.
  • -
  • You must have Kubernetes DNS configured in your cluster.
  • -
-

Steps

-
    -
  • -

    Need Kubernetes version 1.6 and above. -To check the version, enter kubectl version.

    -
  • -
  • -

    The cluster must be configured to use the kube-dns addon. Check with

    -
  • -
-
minikube addons list
-
- -

Kubernetes DNS Page

-
    -
  • Start minikube with the recommended configuration for Spark
  • -
-
minikube start --cpus 3 --memory 4096
-
- -
    -
  • Submit a Spark job using:
  • -
-
$ bin/spark-submit \
-    --master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \
-    --deploy-mode cluster \
-    --name spark-pi \
-    --class org.apache.spark.examples.SparkPi \
-    --conf spark.executor.instances=3 \
-    --conf spark.kubernetes.container.image=<spark-image> \
-    local:///path/to/examples.jar
-
- -

Use kubectl cluster-info to get the K8s API server URL

-

Spark (starting with version 2.3) ships with a Dockerfile in the kubernetes/dockerfiles/ directory.

-
    -
  • Access logs:
  • -
-
$ kubectl -n=<namespace> logs -f <driver-pod-name>
-
- -
    -
  • Accessing Driver UI:
  • -
-
$ kubectl port-forward <driver-pod-name> 4040:4040
-
- -

Then go to http://localhost:4040

-

Alternatives

-

Helm Chart for Spark

-

The same on KubeApps

-
helm install --name my-spark-release --version 0.1.12 stable/spark
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Cloud/AWS.md b/docs/Cloud/AWS.md similarity index 73% rename from docs_src/Cloud/AWS.md rename to docs/Cloud/AWS.md index 69a4ae7..1592369 100644 --- a/docs_src/Cloud/AWS.md +++ b/docs/Cloud/AWS.md @@ -5,93 +5,81 @@ - Compute: EC2 (autoscaling, ELB load balancing) - Networking / Security: VPC (security groups), IAM (users/groups/application roles) - ## Storage - S3: secure, scalable object-level storage, static web site hosting... - Glacier: long-term storage - EBS: block-level storage (for EC2 instances) - ## Databases - RDS: relational databases (MySQL, PostgreSQL, MSSQL, MariaDB, Aurora...) - DynamoDB: scalable NoSQL database backed by solid-state drives - ## Analytics - RedShift: PostgreSQL-based columnstore OLAP database that uses SQL. MPP architecture. - EMR: Hadoop cluster (Hive, Pig, HBase, Spark...). - ## ETL / ELT / Batch Processing - Glue - Batch - Data Pipeline: orchestrate data transfers between S3, DynamoDB, Redshift - ## Application Services - Notifications: SNS (alerts by email, SMS...), SES (bulk email) -- Queue: SQS (async message queues for component decoupling) +- Queue: SQS (async message queues for component decoupling) - Workflows, State Machine as a Service: AWS Step Functions, SWF (task-oriented workflows - complicated) - Document Search: ElasticSearch, CloudSearch - ## Monitoring - Cloudwatch (monitor services and instances e.g. CPU utilization, etc...) - CloudTrail (monitor API calls) - ## Infrastructure Deployment / Automation - Elastic Beanstalk (simple, mostly web or Linux worker) - CloudFormation (JSON / YAML templates - more difficult, but many existing templates) - OpsWork (higher level than CloudFormation, uses non-native components - Chef-based) - ## Desktop in the Cloud - WorkSpaces - # Details ## Tools -- Unix tools on Windows: [Cygwin]( http://www.cygwin.com/ ) +- Unix tools on Windows: [Cygwin]( https://www.cygwin.com/ ) -- Putty SSH client for Windows [doc]( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/get-set-up-for-amazon-ec2.html ) +- Putty SSH client for Windows [doc]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/get-set-up-for-amazon-ec2.html ) -1. Download and install PuTTY [link]( http://www.chiark.greenend.org.uk/~sgtatham/putty/ ). Be sure to install the entire suite. +1. Download and install PuTTY [link]( https://www.chiark.greenend.org.uk/~sgtatham/putty/ ). Be sure to install the entire suite. 2. Start PuTTYgen (for example, from the Start menu, click All Programs > PuTTY > PuTTYgen). 3. Under Type of key to generate, select SSH-2 RSA. -4. Load the .pem file (private key) downloaded from the console (in "credentials" folder) +4. Load the .pem file (private key) downloaded from the console (in "credentials" folder) 5. Save private key -- AWS [command line interface]( http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html ) +- AWS [command line interface]( https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html ) -- [AWS toolkit for Visual Studio]( http://docs.aws.amazon.com/AWSToolkitVS/latest/UserGuide/welcome.html ) +- [AWS toolkit for Visual Studio]( https://docs.aws.amazon.com/AWSToolkitVS/latest/UserGuide/welcome.html ) - [AWS tools for PowerShell]( https://aws.amazon.com/documentation/powershell/ ) - ## AWS EC2 -- Log onto instance with [Putty SSH]( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html#using-putty) +- Log onto instance with [Putty SSH]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html#using-putty) login as: ec2-user (Amazon Linux) or: ubuntu -[Bash shell documentation]( http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html ) - - -- Use a shell script to configure the instance [link]( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html ) +[Bash shell documentation]( https://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html ) -* User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the "As file" option and browse for the file to attach. +- Use a shell script to configure the instance [link]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html ) +- User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the "As file" option and browse for the file to attach. ## AWS S3 @@ -106,27 +94,26 @@ Command-line s3 clients: - AWS command line (see above) - S3 command line tools - ## Redshift 1) Use Case - Large-scale SQL analytical database - Querying in Redshift is FAST -- Full SQL compared to [HiveQL](http://hive.apache.org/) +- Full SQL compared to [HiveQL](https://hive.apache.org/) - Redshift isn’t a complete replacement for a Hadoop system (no streaming, no text processing) 2) Tools -- install SQL [tool]( http://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-prereq.html ) -- or [Aginity]( http://www.aginity.com/workbench/redshift/ ) -- Microsoft [SSDT]( http://stackoverflow.com/questions/17323590/redshift-with-ssis-ssdt ) +- install SQL [tool]( https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-prereq.html ) +- or [Aginity]( https://www.aginity.com/workbench/redshift/ ) +- Microsoft [SSDT]( https://stackoverflow.com/questions/17323590/redshift-with-ssis-ssdt ) 3) Get data into Redshift: -* COPY from S3 (delimited text files) -* COPY from DynamoDB (NoSQL datastore) -* JDBC/ODBC transactions (not efficient for bulk loading) +- COPY from S3 (delimited text files) +- COPY from DynamoDB (NoSQL datastore) +- JDBC/ODBC transactions (not efficient for bulk loading) Tables have ‘keys’ that define how the data is split across slices. The recommended practice is to split based upon commonly-joined columns, so that joined data resides on the same slice, thus avoiding the need to move data between systems. @@ -140,10 +127,9 @@ SELECT COUNT(DISTINCT field2) FROM table1 ## EMR -- [EMR FAQs]( http://aws.amazon.com/elasticmapreduce/faqs/ ) -- [Extract, Transform, and Load (ETL) Data with Amazon EMR]( http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/emr-etl.html ) -- [EMR article]( http://aws.amazon.com/articles/Elastic-MapReduce ) - +- [EMR FAQs]( https://aws.amazon.com/elasticmapreduce/faqs/ ) +- [Extract, Transform, and Load (ETL) Data with Amazon EMR]( https://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/emr-etl.html ) +- [EMR article]( https://aws.amazon.com/articles/Elastic-MapReduce ) ## SWF @@ -152,4 +138,3 @@ The Amazon Simple Workflow Service (Amazon SWF) makes it easy to build applicati When using Amazon SWF, you implement workers to perform tasks. These workers can run either on cloud infrastructure, such as Amazon Elastic Compute Cloud (Amazon EC2), or on your own premises. You can create tasks that are long-running, or that may fail, time out, or require restarts—or that may complete with varying throughput and latency. Amazon SWF stores tasks and assigns them to workers when they are ready, tracks their progress, and maintains their state, including details on their completion. To coordinate tasks, you write a program that gets the latest state of each task from Amazon SWF and uses it to initiate subsequent tasks. Amazon SWF maintains an application's execution state durably so that the application is resilient to failures in individual components. With Amazon SWF, you can implement, deploy, scale, and modify these application components independently. Amazon SWF offers capabilities to support a variety of application requirements. It is suitable for a range of use cases that require coordination of tasks, including media processing, web application back-ends, business process workflows, and analytics pipelines. - diff --git a/docs/Cloud/AWS/index.html b/docs/Cloud/AWS/index.html deleted file mode 100644 index 986347a..0000000 --- a/docs/Cloud/AWS/index.html +++ /dev/null @@ -1,2211 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - AWS Services Overview - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
- -
- - -
-
- - - - - - - -

AWS Services Overview

-

Basic Services

-
    -
  • Compute: EC2 (autoscaling, ELB load balancing)
  • -
  • Networking / Security: VPC (security groups), IAM (users/groups/application roles)
  • -
-

Storage

-
    -
  • S3: secure, scalable object-level storage, static web site hosting...
  • -
  • Glacier: long-term storage
  • -
  • EBS: block-level storage (for EC2 instances)
  • -
-

Databases

-
    -
  • RDS: relational databases (MySQL, PostgreSQL, MSSQL, MariaDB, Aurora...)
  • -
  • DynamoDB: scalable NoSQL database backed by solid-state drives
  • -
-

Analytics

-
    -
  • RedShift: PostgreSQL-based columnstore OLAP database that uses SQL. MPP architecture.
  • -
  • EMR: Hadoop cluster (Hive, Pig, HBase, Spark...).
  • -
-

ETL / ELT / Batch Processing

-
    -
  • Glue
  • -
  • Batch
  • -
  • Data Pipeline: orchestrate data transfers between S3, DynamoDB, Redshift
  • -
-

Application Services

-
    -
  • Notifications: SNS (alerts by email, SMS...), SES (bulk email)
  • -
  • Queue: SQS (async message queues for component decoupling)
  • -
  • Workflows, State Machine as a Service: AWS Step Functions, SWF (task-oriented workflows - complicated)
  • -
  • Document Search: ElasticSearch, CloudSearch
  • -
-

Monitoring

-
    -
  • Cloudwatch (monitor services and instances e.g. CPU utilization, etc...)
  • -
  • CloudTrail (monitor API calls)
  • -
-

Infrastructure Deployment / Automation

-
    -
  • Elastic Beanstalk (simple, mostly web or Linux worker)
  • -
  • CloudFormation (JSON / YAML templates - more difficult, but many existing templates)
  • -
  • OpsWork (higher level than CloudFormation, uses non-native components - Chef-based)
  • -
-

Desktop in the Cloud

-
    -
  • WorkSpaces
  • -
-

Details

-

Tools

-
    -
  • -

    Unix tools on Windows: Cygwin

    -
  • -
  • -

    Putty SSH client for Windows doc

    -
  • -
  • -

    Download and install PuTTY link. Be sure to install the entire suite.

    -
  • -
  • Start PuTTYgen (for example, from the Start menu, click All Programs > PuTTY > PuTTYgen).
  • -
  • Under Type of key to generate, select SSH-2 RSA.
  • -
  • Load the .pem file (private key) downloaded from the console (in "credentials" folder)
  • -
  • -

    Save private key

    -
  • -
  • -

    AWS command line interface

    -
  • -
  • -

    AWS toolkit for Visual Studio

    -
  • -
  • -

    AWS tools for PowerShell

    -
  • -
-

AWS EC2

- -

login as: ec2-user (Amazon Linux) or: ubuntu

-

Bash shell documentation

-
    -
  • -

    Use a shell script to configure the instance link

    -
  • -
  • -

    User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the "As file" option and browse for the file to attach.

    -
  • -
-

AWS S3

-

GUI tools to upload / manage files:

-
    -
  • AWS Console
  • -
  • S3 Browser
  • -
  • CloudBerry
  • -
-

Command-line s3 clients:

-
    -
  • AWS command line (see above)
  • -
  • S3 command line tools
  • -
-

Redshift

-

1) Use Case

-
    -
  • Large-scale SQL analytical database
  • -
  • Querying in Redshift is FAST
  • -
  • Full SQL compared to HiveQL
  • -
  • Redshift isn’t a complete replacement for a Hadoop system (no streaming, no text processing)
  • -
-

2) Tools

- -

3) Get data into Redshift:

-
    -
  • COPY from S3 (delimited text files)
  • -
  • COPY from DynamoDB (NoSQL datastore)
  • -
  • JDBC/ODBC transactions (not efficient for bulk loading)
  • -
-

Tables have ‘keys’ that define how the data is split across slices. The recommended practice is to split based upon commonly-joined columns, so that joined data resides on the same slice, thus avoiding the need to move data between systems.

-

4) Examples:

-
COPY table1 FROM 's3://bucket1/' credentials 'aws_access_key_id=abc;aws_secret_access_key=xyz' delimiter '|' gzip removequotes truncatecolumns maxerror 1000
-SELECT DISTINCT field1 FROM table1
-SELECT COUNT(DISTINCT field2) FROM table1
-
- -

EMR

- -

SWF

-

The Amazon Simple Workflow Service (Amazon SWF) makes it easy to build applications that coordinate work across distributed components. In Amazon SWF, a task represents a logical unit of work that is performed by a component of your application. Coordinating tasks across the application involves managing intertask dependencies, scheduling, and concurrency in accordance with the logical flow of the application. Amazon SWF gives you full control over implementing tasks and coordinating them without worrying about underlying complexities such as tracking their progress and maintaining their state.

-

When using Amazon SWF, you implement workers to perform tasks. These workers can run either on cloud infrastructure, such as Amazon Elastic Compute Cloud (Amazon EC2), or on your own premises. You can create tasks that are long-running, or that may fail, time out, or require restarts—or that may complete with varying throughput and latency. Amazon SWF stores tasks and assigns them to workers when they are ready, tracks their progress, and maintains their state, including details on their completion. To coordinate tasks, you write a program that gets the latest state of each task from Amazon SWF and uses it to initiate subsequent tasks. Amazon SWF maintains an application's execution state durably so that the application is resilient to failures in individual components. With Amazon SWF, you can implement, deploy, scale, and modify these application components independently.

-

Amazon SWF offers capabilities to support a variety of application requirements. It is suitable for a range of use cases that require coordination of tasks, including media processing, web application back-ends, business process workflows, and analytics pipelines.

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Cloud/AWS_Lambda.md b/docs/Cloud/AWS_Lambda.md similarity index 99% rename from docs_src/Cloud/AWS_Lambda.md rename to docs/Cloud/AWS_Lambda.md index ef963c2..60b4b0b 100644 --- a/docs_src/Cloud/AWS_Lambda.md +++ b/docs/Cloud/AWS_Lambda.md @@ -9,5 +9,3 @@ tags: aws lambda cloud [Building a Dynamic DNS for Route 53 using CloudWatch Events and Lambda]( https://github.com/awslabs/aws-lambda-ddns-function ) [Lambkin]( https://github.com/jarpy/lambkin ) - CLI tool for generating and managing simple functions in AWS Lambda - - diff --git a/docs/Cloud/AWS_Lambda/index.html b/docs/Cloud/AWS_Lambda/index.html deleted file mode 100644 index e3bc361..0000000 --- a/docs/Cloud/AWS_Lambda/index.html +++ /dev/null @@ -1,1959 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - AWS Lambda - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Cloud/Serverless.md b/docs/Cloud/Serverless.md similarity index 99% rename from docs_src/Cloud/Serverless.md rename to docs/Cloud/Serverless.md index a8364b3..9a02b3c 100644 --- a/docs_src/Cloud/Serverless.md +++ b/docs/Cloud/Serverless.md @@ -24,7 +24,6 @@ npm install -g serverless [C# example](https://serverless.com/blog/serverless-v1.4.0/) - ## Cheatsheet * Create a Service: diff --git a/docs/Cloud/Serverless/index.html b/docs/Cloud/Serverless/index.html deleted file mode 100644 index 87988b9..0000000 --- a/docs/Cloud/Serverless/index.html +++ /dev/null @@ -1,2044 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Serverless Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Serverless Cheatsheet

-

Serverless home page

-

Install

-
npm install -g serverless
-
- -

Examples

-

Serverless Examples

-

Serverless Starter

-

Python example

-

C# example

-

Cheatsheet

-
    -
  • Create a Service:
  • -
-
# NodeJS
-serverless create -p [SERVICE NAME] -t aws-nodejs
-
-# C#
-serverless create --path serverlessCSharp --template aws-csharp
-
- -
    -
  • Install a Service
  • -
-

This is a convenience method to install a pre-made Serverless Service locally by downloading the Github repo and unzipping it.

-
serverless install -u [GITHUB URL OF SERVICE]
-
- -
    -
  • Deploy All
  • -
-

Use this when you have made changes to your Functions, Events or Resources in serverless.yml or you simply want to deploy all changes within your Service at the same time.

-
serverless deploy -s [STAGE NAME] -r [REGION NAME] -v
-
- -
    -
  • Deploy Function
  • -
-

Use this to quickly overwrite your AWS Lambda code on AWS, allowing you to develop faster.

-
serverless deploy function -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME]
-
- -
    -
  • Invoke Function
  • -
-

Invokes an AWS Lambda Function on AWS and returns logs.

-
serverless invoke -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME] -l
-
- -
    -
  • Streaming Logs
  • -
-

Open up a separate tab in your console and stream all logs for a specific Function using this command.

-
serverless logs -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME]
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Debug_Kubernetes.md b/docs/Containers/Debug_Kubernetes.md similarity index 85% rename from docs_src/Containers/Debug_Kubernetes.md rename to docs/Containers/Debug_Kubernetes.md index 63598fc..9776919 100644 --- a/docs_src/Containers/Debug_Kubernetes.md +++ b/docs/Containers/Debug_Kubernetes.md @@ -18,7 +18,7 @@ To override the entrypoint, use: winpty docker run --rm -p : -it --entrypoint bash : ``` -The above assumes you are using cygwin / git bash on Windows. +The above assumes you are using cygwin / git bash on Windows. ### Run a test K8s pod @@ -27,11 +27,11 @@ kubectl run --image=: ``` Useful options: -- ``--restart=Never`` -- if the pod has a console: ``-i --tty --command -- bash`` +- ``--restart=Never`` +- if the pod has a console: ``-i --tty --command -- bash`` -- Attach to the (first) container in the Pod: +- Attach to the (first) container in the Pod: ```shell kubectl attach -i -t @@ -49,4 +49,4 @@ kubectl exec -it -- bash ```shell kubectl delete pod -``` \ No newline at end of file +``` diff --git a/docs/Containers/Debug_Kubernetes/index.html b/docs/Containers/Debug_Kubernetes/index.html deleted file mode 100644 index a9d71ba..0000000 --- a/docs/Containers/Debug_Kubernetes/index.html +++ /dev/null @@ -1,2007 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Debug Kubernetes - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Debug Kubernetes

- -

Run a test Docker container

-
docker run --rm -p <port>:<port> <docker image>:<tag>
-docker ps
-# cleanup
-docker kill <container>
-
- -

To override the entrypoint, use:

-
winpty docker run --rm -p <port>:<port> -it --entrypoint bash <docker image>:<tag>
-
- -

The above assumes you are using cygwin / git bash on Windows.

-

Run a test K8s pod

-
kubectl run <deployment name> --image=<docker image>:<tag>
-
- -

Useful options: -- --restart=Never -- if the pod has a console: -i --tty --command -- bash

-
    -
  • Attach to the (first) container in the Pod:
  • -
-
kubectl attach <pod name> -i -t
-
- -

If there are multiple containers in the pod, use: -c <container name>

-
    -
  • Get a shell to a running Container:
  • -
-
kubectl exec -it <pod name> -- bash
-
- -
    -
  • Delete test pod:
  • -
-
kubectl delete pod <pod name>
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Deploy_to_Kubernetes (Helm).md b/docs/Containers/Deploy_to_Kubernetes (Helm).md similarity index 89% rename from docs_src/Containers/Deploy_to_Kubernetes (Helm).md rename to docs/Containers/Deploy_to_Kubernetes (Helm).md index b1c8281..6e746bd 100644 --- a/docs_src/Containers/Deploy_to_Kubernetes (Helm).md +++ b/docs/Containers/Deploy_to_Kubernetes (Helm).md @@ -13,7 +13,6 @@ tags: Kubernetes MiniKube Kubectl [Helm]( https://helm.sh/ ) - ## Deployment of a ``sbt``-built app on Kubernetes (MiniKube) ### Test packaging without Kubernetes first @@ -21,11 +20,11 @@ tags: Kubernetes MiniKube Kubectl - Stage all Play files in a local directory and verify ```shell -sbt stage +sbt stage ``` - For direct deployment, create a distribution in ``target/universal`` - + ```shell sbt dist ``` @@ -34,7 +33,7 @@ The ``dist`` task builds a binary version of your application that you can deplo ### Deploy a Helm chart to Kubernetes -Prerequisites: ``minikube``, ``kubectl``, ``docker`` client and ``helm`` should be installed +Prerequisites: ``minikube``, ``kubectl``, ``docker`` client and ``helm`` should be installed - Generate the Dockerfile and environment prepared for creating a Docker image @@ -42,7 +41,7 @@ Prerequisites: ``minikube``, ``kubectl``, ``docker`` client and ``helm`` should sbt docker:stage ``` -- Verify the output under ``target/docker`` +- Verify the output under ``target/docker`` - Start ``minikube`` @@ -65,7 +64,7 @@ Also consider enabling ``heapster`` kubectl get nodes ``` -It should return one node. +It should return one node. - Connect the Docker client to the Docker daemon in the K8s VM @@ -76,10 +75,10 @@ eval $(minikube docker-env) Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as ``:latest``, with pull image policy of ``Always`` correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. -- If needed, remove previously built images from the local Docker server with ``sbt docker:clean`` or ``docker rmi ``. +- If needed, remove previously built images from the local Docker server with ``sbt docker:clean`` or ``docker rmi ``. To view the list of Docker images, run ``docker images`` -- Build the Docker image and publish it to Kubernetes' Docker server. +- Build the Docker image and publish it to Kubernetes' Docker server. ```shell sbt docker:publishLocal @@ -100,7 +99,7 @@ and if that looks OK or specify a release name: ```shell -./helm install --name +./helm install --name ``` - Verify the Helm deployment to ``minikube`` @@ -123,18 +122,18 @@ kubectl get pods ```shell kubectl get pods -kubectl port-forward 8080: -curl -v http://localhost:8080/api +kubectl port-forward 8080: +curl -v https://localhost:8080/api ``` ``kubectl port-forward`` also allows using resource name, such as a service name, to select a matching pod to port forward to ```shell -kubectl port-forward svc/ 8080: -curl -v http://localhost:8080/ +kubectl port-forward svc/ 8080: +curl -v https://localhost:8080/ ``` -- When needed, delete the release with +- When needed, delete the release with ```shell helm ls @@ -160,7 +159,6 @@ minikube addons enable ingress See [Blog]( https://medium.com/@Oskarr3/setting-up-ingress-on-minikube-6ae825e98f82 ) - ### SSL Termination (TO DO) [IBM Ingress TLS tutorial]( https://www.ibm.com/support/knowledgecenter/en/SS5PWC/front_end_tls_ingress_task.html ) @@ -189,7 +187,7 @@ kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE} kubectl create secret tls my-secret --key tls.key --cert tls.crt ``` -Add under ``spec:`` in +Add under ``spec:`` in ```yaml tls: diff --git a/docs/Containers/Deploy_to_Kubernetes (Helm)/index.html b/docs/Containers/Deploy_to_Kubernetes (Helm)/index.html deleted file mode 100644 index efd3ce1..0000000 --- a/docs/Containers/Deploy_to_Kubernetes (Helm)/index.html +++ /dev/null @@ -1,2213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Deploy to Kubernetes (Helm) - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Deploy to Kubernetes (Helm)

- - -

Deploying scala sbt microservice to Kubernetes

-

SBT Native Packager - Docker

-

OpenSSL

-

Helm

-

Deployment of a sbt-built app on Kubernetes (MiniKube)

-

Test packaging without Kubernetes first

-
    -
  • Stage all Play files in a local directory and verify
  • -
-
sbt stage 
-
- -
    -
  • For direct deployment, create a distribution in target/universal
  • -
-
sbt dist
-
- -

The dist task builds a binary version of your application that you can deploy to a server without any dependency on SBT, the only thing the server needs is a Java installation.

-

Deploy a Helm chart to Kubernetes

-

Prerequisites: minikube, kubectl, docker client and helm should be installed

-
    -
  • Generate the Dockerfile and environment prepared for creating a Docker image
  • -
-
sbt docker:stage
-
- -
    -
  • -

    Verify the output under target/docker

    -
  • -
  • -

    Start minikube

    -
  • -
-
minikube start
-
- -
    -
  • Enable Ingress
  • -
-
minikube addons list
-minikube addons enable ingress
-
- -

Also consider enabling heapster

-
    -
  • List available nodes to verify that kubectl is properly configured
  • -
-
kubectl get nodes
-
- -

It should return one node.

-
    -
  • Connect the Docker client to the Docker daemon in the K8s VM
  • -
-
eval $(minikube docker-env)
-
- -

Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. -Otherwise, if you do not specify version of your image, it will be assumed as :latest, with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet.

-
    -
  • -

    If needed, remove previously built images from the local Docker server with sbt docker:clean or docker rmi <image>. -To view the list of Docker images, run docker images

    -
  • -
  • -

    Build the Docker image and publish it to Kubernetes' Docker server.

    -
  • -
-
sbt docker:publishLocal
-
- -
    -
  • Deploy the Helm chart
  • -
-
./helm install --dry-run --debug <helm chart folder> &> output.txt
-
- -

and if that looks OK

-
./helm install <helm chart folder>
-
- -

or specify a release name:

-
./helm install --name <release name> <helm chart folder> 
-
- -
    -
  • Verify the Helm deployment to minikube
  • -
-
./helm list
-./helm status <release name>
-
- -

More details via:

-
kubectl get ing
-kubectl get service
-kubectl get deployment
-kubectl get pods
-
- -
    -
  • Test the deployment by forwarding a local port to a port on the pod
  • -
-
kubectl get pods
-kubectl port-forward <pod name> 8080:<target port on pod> 
-curl -v http://localhost:8080/api
-
- -

kubectl port-forward also allows using resource name, such as a service name, to select a matching pod to port forward to

-
kubectl port-forward svc/<service name>  8080:<service port> 
-curl -v http://localhost:8080/
-
- -
    -
  • When needed, delete the release with
  • -
-
helm ls
-helm delete <release name>
-
- -

If you want to deploy / not deploy an Ingress

-
    -
  • Update values.yaml in the Helm chart root folder
  • -
-
ingress:
-  enabled: true  # or: false; true by default
-
- -
    -
  • If true, make sure the minikube Ingress add-on is enabled
  • -
-
minikube addons enable ingress
-
- -
    -
  • Deploy on Kubernetes as above
  • -
-

See Blog

-

SSL Termination (TO DO)

-

IBM Ingress TLS tutorial

-
    -
  • Generate a x509, pem encoded, RSA 2048 certificate with OpenSSL
  • -
-
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}"
-
-openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=john-cd.com"
-
- -

Note: To find myhost.com for minikube, run the following commands:

-
 $ minikube ssh
- $ echo $HOSTNAME
- minikube
-
- -
    -
  • Create a Kubernetes secret
  • -
-
kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE}
-
-kubectl create secret tls my-secret --key tls.key --cert tls.crt
-
- -

Add under spec: in

-
  tls:
-  - hosts:
-    - myhost.com
-    secretName: my-secret
-
- -

Find and delete all nginx pods to force the nginx.conf to update and reflect the ingress changes. Find the ingress pods with the following:

-
kubectl get pods --all-namespaces
-kubectl delete pods --namespace=kube-system [ingress pod]
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Deploy_to_Kubernetes.md b/docs/Containers/Deploy_to_Kubernetes.md similarity index 84% rename from docs_src/Containers/Deploy_to_Kubernetes.md rename to docs/Containers/Deploy_to_Kubernetes.md index 8388031..8fa32bc 100644 --- a/docs_src/Containers/Deploy_to_Kubernetes.md +++ b/docs/Containers/Deploy_to_Kubernetes.md @@ -8,7 +8,7 @@ using ``kubectl`` ### Create ConfigMap from config files A [ConfigMap]( https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ ) stores K8s-specific configuration that can be mounted as volume or used in env variables. -It is often used to provide production configuration: application configuration, log settings, etc... +It is often used to provide production configuration: application configuration, log settings, etc... ```shell kubectl create configmap app-conf --from-file= # create a ConfigMap from multiple files in the same directory. @@ -19,16 +19,16 @@ kubectl create configmap app-conf --from-file= # create a ```bash kubectl get configmap app-conf -o yaml -# or +# or -kubectl describe configmaps app-conf +kubectl describe configmaps app-conf ``` ### Create a Kubernetes secret -You may need a Secret to store database passwords and secret keys. +You may need a Secret to store database passwords and secret keys. -For applications using the [Play Framework]( https://www.playframework.com/ ), generate a secret using: +For applications using the [Play Framework]( https://www.playframework.com/ ), generate a secret using: ```shell secretText = $(sbt playGenerateSecret) @@ -37,15 +37,15 @@ f [[ $secretText =~ $regex ]] then secret = "${BASH_REMATCH[1]}" echo $secret - kubectl create secret generic application-secret --from-literal=application_secret=$secret - kubectl get secrets - else + kubectl create secret generic application-secret --from-literal=application_secret=$secret + kubectl get secrets + else echo "$secretText doesn't match" >&2 fi done ``` -### Create Resources (Deployment, Service, Ingress, etc...) +### Create Resources (Deployment, Service, Ingress, etc...) ```shell kubectl create -f @@ -66,9 +66,9 @@ kubectl get pods kubectl delete deployment ``` -### Install an Ingress Controller +### Install an Ingress Controller -- An ingress controller is necessary to make Ingresses work. See the [Ingress doc]( https://kubernetes.io/docs/concepts/services-networking/ingress/ ) +- An ingress controller is necessary to make Ingresses work. See the [Ingress doc]( https://kubernetes.io/docs/concepts/services-networking/ingress/ ) #### Minikube @@ -84,7 +84,6 @@ Enabling the add-on provisions the following: - the Nginx ingress controller - a service that exposes a default Nginx backend pod for handling unmapped requests. - #### Install the nginx ingress controller (non-minikube Kubernetes) - Install via this [helm chart]( https://hub.kubeapps.com/charts/stable/nginx-ingress ) @@ -100,8 +99,8 @@ helm install --name nginx-ingress-release stable/nginx-ingress \ --set controller.stats.enabled=true \ --set controller.metrics.enabled=true ``` - -- Verify that the Ingress exists + +- Verify that the Ingress exists ```shell kubectl get ing @@ -111,7 +110,6 @@ See [explanations]( https://daemonza.github.io/2017/02/13/kubernetes-nginx-ingre The nginx ingress controller requires a 404-server like [this]( https://github.com/kubernetes/ingress-nginx/tree/master/images/404-server ) - #### Alternative ingress controllers -- Install [https://traefik.io/]( https://traefik.io/ ) \ No newline at end of file +- Install [https://traefik.io/]( https://traefik.io/ ) diff --git a/docs/Containers/Deploy_to_Kubernetes/index.html b/docs/Containers/Deploy_to_Kubernetes/index.html deleted file mode 100644 index 83cd025..0000000 --- a/docs/Containers/Deploy_to_Kubernetes/index.html +++ /dev/null @@ -1,2147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Deploy to Kubernetes - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Deploy to Kubernetes

- -

using kubectl

-

Create ConfigMap from config files

-

A ConfigMap stores K8s-specific configuration that can be mounted as volume or used in env variables. -It is often used to provide production configuration: application configuration, log settings, etc...

-
kubectl create configmap app-conf --from-file=<path to config files>  # create a ConfigMap from multiple files in the same directory.
-
- -
    -
  • Check the ConfigMap
  • -
-
kubectl get configmap app-conf -o yaml
-
-# or 
-
-kubectl describe configmaps app-conf 
-
- -

Create a Kubernetes secret

-

You may need a Secret to store database passwords and secret keys.

-

For applications using the Play Framework, generate a secret using:

-
secretText = $(sbt playGenerateSecret)
-regex = "Generated new secret: (.+)$"
-f [[ $secretText =~ $regex ]]
-    then
-        secret = "${BASH_REMATCH[1]}"
-        echo $secret
-        kubectl create secret generic application-secret --from-literal=application_secret=$secret
-        kubectl get secrets
-    else
-        echo "$secretText doesn't match" >&2
-    fi
-done
-
- -

Create Resources (Deployment, Service, Ingress, etc...)

-
kubectl create -f <path/to/resource_config.yaml>
-
- -
    -
  • Verify proper resource creation
  • -
-
kubectl get ing
-kubectl get service
-kubectl get deployment
-kubectl get pods
-
- -
    -
  • To delete a resource later, in this case a Deployment:
  • -
-
kubectl delete deployment <deployment name>
-
- -

Install an Ingress Controller

-
    -
  • An ingress controller is necessary to make Ingresses work. See the Ingress doc
  • -
-

Minikube

-
    -
  • minikube provides its own ingress controller via the Ingress add-on:
  • -
-
minikube addons enable ingress
-
- -

Enabling the add-on provisions the following:

-
    -
  • a configMap for the Nginx loadbalancer
  • -
  • the Nginx ingress controller
  • -
  • a service that exposes a default Nginx backend pod for handling unmapped requests.
  • -
-

Install the nginx ingress controller (non-minikube Kubernetes)

- -
#./helm install stable/nginx-ingress
-
- -

or with stat collection enabled for Prometheus

-
helm install --name nginx-ingress-release stable/nginx-ingress \
-  --set controller.stats.enabled=true \
-  --set controller.metrics.enabled=true
-
- -
    -
  • Verify that the Ingress exists
  • -
-
kubectl get ing
-
- -

See explanations and documentation

-

The nginx ingress controller requires a 404-server like this

-

Alternative ingress controllers

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Docker.md b/docs/Containers/Docker.md similarity index 76% rename from docs_src/Containers/Docker.md rename to docs/Containers/Docker.md index ffd0eb2..8daef3e 100644 --- a/docs_src/Containers/Docker.md +++ b/docs/Containers/Docker.md @@ -2,6 +2,7 @@ title: Docker Cheatsheet category: devops --- + # Docker Cheatsheet ## Useful Links @@ -27,44 +28,44 @@ Docker registries hold images. To show only running containers use: ```bash -$ docker ps +docker ps ``` To show all containers use: ```bash -$ docker ps -a +docker ps -a ``` Show last started container: ```bash -$ docker ps -l +docker ps -l ``` Download an image: ```bash -$ docker pull centos +docker pull centos ``` Create then start a container: `docker run [OPTIONS] IMAGE [COMMAND] [ARG...]` * [Docker run reference](https://docs.docker.com/engine/reference/run/) ```bash -$ docker run hello-world +docker run hello-world ``` Run with interactive terminal (i = interactive t = terminal): ```bash -$ docker run -it ubuntu bash +docker run -it ubuntu bash ``` Start then detach the container (daemonize): ```bash -$ docker run -d -p8088:80 --name webserver nginx +docker run -d -p8088:80 --name webserver nginx ``` If you want a transient container, `docker run --rm` will remove the container after it stops. @@ -72,32 +73,32 @@ If you want a transient container, `docker run --rm` will remove the container a Looks inside the container (use `-f` to act like `tail -f`): ```bash -$ docker logs +docker logs ``` Stop container: ```bash -$ docker stop # container ID or name +docker stop # container ID or name ``` Delete container: ```bash -$ docker rm +docker rm ``` To check the environment: ```bash -$ docker run -it alpine env +docker run -it alpine env ``` Docker version / info: ```bash -$ docker version -$ docker info +docker version +docker info ``` ## Port Mapping @@ -105,13 +106,13 @@ $ docker info ``-p 80:5000`` would map port 80 on our local host to port 5000 inside our container. ```bash -$ docker run -d -p 80:5000 training/webapp python app.py +docker run -d -p 80:5000 training/webapp python app.py ``` Full format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort ```bash -$ docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py +docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py ``` Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: ``-p1234-1236:1234-1236/tcp`` @@ -119,7 +120,7 @@ Both hostPort and containerPort can be specified as a range of ports. When speci The ``-P`` flag tells Docker to map any required network ports inside our container to our host (using random ports). ```bash -$ docker run -d -P training/webapp python app.py +docker run -d -P training/webapp python app.py ``` ## Linking @@ -128,20 +129,20 @@ $ docker run -d -P training/webapp python app.py The ``--link`` flag also takes the form: ``--link `` ```bash -$ docker run -d --name myES -p 9200:9200 -p 9300:9300 elasticsearch -$ docker run --name myK --link myES:elasticsearch -p 5601:5601 -d docker-kibana-sense +docker run -d --name myES -p 9200:9200 -p 9300:9300 elasticsearch +docker run --name myK --link myES:elasticsearch -p 5601:5601 -d docker-kibana-sense ``` ## Networks ```bash -$ docker network ls +docker network ls ``` Find out the container’s IP address: ```bash -$ docker network inspect bridge +docker network inspect bridge ``` ## Data Volumes @@ -149,8 +150,8 @@ $ docker network inspect bridge Create a new volume inside a container at /webapp: ```bash -$ docker run -d -P --name web -v /webapp training/webapp python app.py -$ docker inspect web +docker run -d -P --name web -v /webapp training/webapp python app.py +docker inspect web ``` You can also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image. @@ -158,7 +159,7 @@ You can also use the VOLUME instruction in a Dockerfile to add one or more new v Mount the host directory, ``/src/webapp``, into the container at ``/opt/webapp``. ```bash -$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py +docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py ``` On Windows, use: ``docker run -v /c/Users/:/ ...`` @@ -166,9 +167,9 @@ On Windows, use: ``docker run -v /c/Users/:/ ...`` ## Example Dockerfile ```bash -$ vim Dockerfile +vim Dockerfile ``` - + ```docker FROM docker/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes @@ -176,5 +177,5 @@ CMD /usr/games/fortune -a | cowsay ``` ```bash -$ docker build -t docker-whale . +docker build -t docker-whale . ``` diff --git a/docs/Containers/Docker/index.html b/docs/Containers/Docker/index.html deleted file mode 100644 index b992f5c..0000000 --- a/docs/Containers/Docker/index.html +++ /dev/null @@ -1,2172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Docker Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Docker Cheatsheet

- -

Docker Cheat Sheet

-

Docker Documentation

-

Docker Tutorials and Labs

-

Docker + Jenkins

-

Docker Hub

-

Concepts

-

A Docker image is a read-only template. For example, an image could contain an Ubuntu operating system with Apache and your web application installed. Images are used to create Docker containers. Docker provides a simple way to build new images or update existing images, or you can download Docker images that other people have already created. Docker images are the buildcomponent of Docker.

-

Docker registries hold images.

-

Cheatsheet

-

To show only running containers use:

-
$ docker ps
-
- -

To show all containers use:

-
$ docker ps -a
-
- -

Show last started container:

-
$ docker ps -l
-
- -

Download an image:

-
$ docker pull centos
-
- -

Create then start a container: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] - * Docker run reference

-
$ docker run hello-world
-
- -

Run with interactive terminal (i = interactive t = terminal):

-
$ docker run -it ubuntu bash
-
- -

Start then detach the container (daemonize):

-
$ docker run -d -p8088:80 --name webserver nginx
-
- -

If you want a transient container, docker run --rm will remove the container after it stops.

-

Looks inside the container (use -f to act like tail -f):

-
$ docker logs <container name>
-
- -

Stop container:

-
$ docker stop <container name>   # container ID or name
-
- -

Delete container:

-
$ docker rm <container name>
-
- -

To check the environment:

-
$ docker run -it alpine env 
-
- -

Docker version / info:

-
$ docker version
-$ docker info
-
- -

Port Mapping

-

-p 80:5000 would map port 80 on our local host to port 5000 inside our container.

-
$ docker run -d -p 80:5000 training/webapp python app.py
-
- -

Full format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort

-
$ docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py
-
- -

Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: -p1234-1236:1234-1236/tcp

-

The -P flag tells Docker to map any required network ports inside our container to our host (using random ports).

-
$ docker run -d -P training/webapp python app.py
-
- -

Linking

-

--link <name or id>:alias where name is the name of the container we’re linking to and alias is an alias for the link name. -The --link flag also takes the form: --link <name or id>

-
$ docker run -d --name myES -p 9200:9200 -p 9300:9300 elasticsearch
-$ docker run --name myK --link myES:elasticsearch  -p 5601:5601 -d docker-kibana-sense
-
- -

Networks

-
$ docker network ls
-
- -

Find out the container’s IP address:

-
$ docker network inspect bridge
-
- -

Data Volumes

-

Create a new volume inside a container at /webapp:

-
$ docker run -d -P --name web -v /webapp training/webapp python app.py
-$ docker inspect web
-
- -

You can also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image.

-

Mount the host directory, /src/webapp, into the container at /opt/webapp.

-
$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
-
- -

On Windows, use: docker run -v /c/Users/<path>:/<container path> ...

-

Example Dockerfile

-
$ vim Dockerfile
-
- -
FROM docker/whalesay:latest
-RUN apt-get -y update && apt-get install -y fortunes
-CMD /usr/games/fortune -a | cowsay
-
- -
$ docker build -t docker-whale .
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Helm_Chart_Creation.md b/docs/Containers/Helm_Chart_Creation.md similarity index 98% rename from docs_src/Containers/Helm_Chart_Creation.md rename to docs/Containers/Helm_Chart_Creation.md index e91df52..1c3704e 100644 --- a/docs_src/Containers/Helm_Chart_Creation.md +++ b/docs/Containers/Helm_Chart_Creation.md @@ -29,6 +29,6 @@ Add a remote repo and, from the chart directory, run: -``` +```bash ../helm dependency update ``` diff --git a/docs/Containers/Helm_Chart_Creation/index.html b/docs/Containers/Helm_Chart_Creation/index.html deleted file mode 100644 index ab5f097..0000000 --- a/docs/Containers/Helm_Chart_Creation/index.html +++ /dev/null @@ -1,2015 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Helm Chart Creation - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Helm Chart Creation

- - -

How to create your first Helm chart

-

Steps

-
./helm create <folder containing chart>
-
-./helm lint <folder>
-
-./helm install --dry-run --debug <folder>
-
- -

To create dependencies between charts

-

Create requirements.yaml

-

Add a remote repo

-
./helm repo add stable https://kubernetes-charts.storage.googleapis.com
-
- -

and, from the chart directory, run:

-
../helm dependency update
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Kubernetes_Cheatsheet.md b/docs/Containers/Kubernetes_Cheatsheet.md similarity index 86% rename from docs_src/Containers/Kubernetes_Cheatsheet.md rename to docs/Containers/Kubernetes_Cheatsheet.md index 019269b..b66e785 100644 --- a/docs_src/Containers/Kubernetes_Cheatsheet.md +++ b/docs/Containers/Kubernetes_Cheatsheet.md @@ -24,28 +24,24 @@ kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --imag ``` - ``kubectl get`` - list resources. - - ``kubectl get deployment`` to get all deployments - - ``kubectl get pods -l app=nginx`` to get pods with label "app: nginx" + - ``kubectl get deployment`` to get all deployments + - ``kubectl get pods -l app=nginx`` to get pods with label "app: nginx" - ``kubectl describe`` - show detailed information about a resource - ``kubectl logs`` - print the logs from a container in a pod - ``kubectl exec`` - execute a command on a container in a pod - ### Using the Docker daemon in the Minikube VM When using a single VM of Kubernetes, it’s really handy to reuse the minikube’s built-in Docker daemon ```shell eval $(minikube docker-env) -# test with +# test with docker ps ``` -Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. +Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as ``:latest``, with pull image policy of ``Always`` correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. -A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. +A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. See [installing Docker]( https://docs.docker.com/install/ ) for instructions for your platform. - - - diff --git a/docs/Containers/Kubernetes_Cheatsheet/index.html b/docs/Containers/Kubernetes_Cheatsheet/index.html deleted file mode 100644 index ea0dc29..0000000 --- a/docs/Containers/Kubernetes_Cheatsheet/index.html +++ /dev/null @@ -1,2023 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Kubernetes Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Kubernetes Cheatsheet

- -

minikube

-
    -
  • To access the Kubernetes Dashboard, run this command in a shell after starting Minikube to get the address:
  • -
-
minikube dashboard
-
- -
    -
  • The minikube VM is exposed to the host system via a host-only IP address, that can be obtained with the minikube ip command
  • -
-

kubectl

-

kubectl Cheat Sheet

-
    -
  • Run a particular image on the cluster (creates a deployment automatically)
  • -
-
kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0  --port=8080
-
- -
    -
  • kubectl get - list resources.
      -
    • kubectl get deployment to get all deployments
    • -
    • kubectl get pods -l app=nginx to get pods with label "app: nginx"
    • -
    -
  • -
  • kubectl describe - show detailed information about a resource
  • -
  • kubectl logs - print the logs from a container in a pod
  • -
  • kubectl exec - execute a command on a container in a pod
  • -
-

Using the Docker daemon in the Minikube VM

-

When using a single VM of Kubernetes, it’s really handy to reuse the minikube’s built-in Docker daemon

-
eval $(minikube docker-env)
-# test with 
-docker ps
-
- -

Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. -Otherwise, if you do not specify version of your image, it will be assumed as :latest, with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet.

-

A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. -See installing Docker for instructions for your platform.

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Kubernetes_Concepts.md b/docs/Containers/Kubernetes_Concepts.md similarity index 60% rename from docs_src/Containers/Kubernetes_Concepts.md rename to docs/Containers/Kubernetes_Concepts.md index 0f447b2..82e0138 100644 --- a/docs_src/Containers/Kubernetes_Concepts.md +++ b/docs/Containers/Kubernetes_Concepts.md @@ -3,14 +3,14 @@ title: Kubernetes Concepts tags: Kubernetes --- -- Pods - A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. +- Pods - A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. Kubernetes workloads, such as Deployments and Jobs, are composed of one or more Pods. Shared pod resources include: - - Shared storage, as Volumes - - Networking, as a unique cluster IP address - - Information about how to run each container, such as the container image version or specific ports to use + - Shared storage, as Volumes + - Networking, as a unique cluster IP address + - Information about how to run each container, such as the container image version or specific ports to use -- Nodes: A Pod always runs on a Node. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster. Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster. +- Nodes: A Pod always runs on a Node. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster. Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster. - Deployment - The most common way of running X copies (Pods) of your application. Supports rolling updates to your container images. @@ -18,6 +18,6 @@ Shared pod resources include: - Labels - Identifying metadata that you can use to sort and select sets of API objects. Labels have many applications, including the following: - * To keep the right number of replicas (Pods) running in a Deployment. The specified label is used to stamp the Deployment’s newly created Pods (as the value of the ``spec.template.labels`` configuration field), and to query which Pods it already manages (as the value of ``spec.selector.matchLabels``). - * To tie a Service to a Deployment using the selector field. - * To look for specific subset of Kubernetes objects, when you are using kubectl. For instance, the command kubectl get deployments --selector=app=nginx only displays Deployments from the nginx app. + * To keep the right number of replicas (Pods) running in a Deployment. The specified label is used to stamp the Deployment’s newly created Pods (as the value of the ``spec.template.labels`` configuration field), and to query which Pods it already manages (as the value of ``spec.selector.matchLabels``). + * To tie a Service to a Deployment using the selector field. + * To look for specific subset of Kubernetes objects, when you are using kubectl. For instance, the command kubectl get deployments --selector=app=nginx only displays Deployments from the nginx app. diff --git a/docs/Containers/Kubernetes_Concepts/index.html b/docs/Containers/Kubernetes_Concepts/index.html deleted file mode 100644 index 0bbdf6a..0000000 --- a/docs/Containers/Kubernetes_Concepts/index.html +++ /dev/null @@ -1,1924 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Kubernetes Concepts - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
- - - - - - - -

Kubernetes Concepts

- -
    -
  • -

    Pods - A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. -Kubernetes workloads, such as Deployments and Jobs, are composed of one or more Pods. -Shared pod resources include:

    -
      -
    • Shared storage, as Volumes
    • -
    • Networking, as a unique cluster IP address
    • -
    • Information about how to run each container, such as the container image version or specific ports to use
    • -
    -
  • -
  • -

    Nodes: A Pod always runs on a Node. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster. Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster.

    -
  • -
  • -

    Deployment - The most common way of running X copies (Pods) of your application. Supports rolling updates to your container images.

    -
  • -
  • -

    Service - By itself, a Deployment can’t receive traffic. Setting up a Service is one of the simplest ways to configure a Deployment to receive and loadbalance requests. Depending on the type of Service used, these requests can come from external client apps or be limited to apps within the same cluster. A Service is tied to a specific Deployment using label selection.

    -
  • -
  • -

    Labels - Identifying metadata that you can use to sort and select sets of API objects. Labels have many applications, including the following:

    -
      -
    • To keep the right number of replicas (Pods) running in a Deployment. The specified label is used to stamp the Deployment’s newly created Pods (as the value of the spec.template.labels configuration field), and to query which Pods it already manages (as the value of spec.selector.matchLabels).
    • -
    • To tie a Service to a Deployment using the selector field.
    • -
    • To look for specific subset of Kubernetes objects, when you are using kubectl. For instance, the command kubectl get deployments --selector=app=nginx only displays Deployments from the nginx app.
    • -
    -
  • -
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Kubernetes_Examples.md b/docs/Containers/Kubernetes_Examples.md similarity index 100% rename from docs_src/Containers/Kubernetes_Examples.md rename to docs/Containers/Kubernetes_Examples.md diff --git a/docs/Containers/Kubernetes_Examples/index.html b/docs/Containers/Kubernetes_Examples/index.html deleted file mode 100644 index 1a6b47d..0000000 --- a/docs/Containers/Kubernetes_Examples/index.html +++ /dev/null @@ -1,2054 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Kubernetes Examples - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Kubernetes Examples

- -

Service + Deployment example

-
apiVersion: v1
-kind: Service
-metadata:
-  name: p2p-robot-service
-spec:
-  selector:
-    app: p2p-robot
-  ports:
-  - name: http
-    protocol: TCP
-    port: 80
-    targetPort: http    # can a text label (port name) or port number
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: p2p-robot-deployment
-spec:
-  selector:
-    matchLabels:
-      app: p2p-robot
-  replicas: 2          # tells deployment to run 2 pods matching the template
-  template:            # create pods using pod definition in this template
-    metadata:
-      # the name is not included in the meta data as a unique name is
-      # generated from the deployment name
-      labels:
-        app: p2p-robot # label used above in matchLabels
-    spec:
-        containers:
-        - name: p2p-robot
-          image: "johncd/p2p-robot:1.0.0"
-          imagePullPolicy: IfNotPresent
-          ports:
-          - containerPort: 9000
-            name: http
-          env:
-          - name: APPLICATION_SECRET    #  Place the application secret in an environment variable, which is read in application.conf 
-            valueFrom:
-                secretKeyRef:
-                  name: application-secret
-                  key: application_secret           
-          volumeMounts:
-          - name: conf-volume
-            mountPath: /usr/local/etc
-        volumes:
-        - name: conf-volume
-          configMap:            # The configMap resource provides a way to inject configuration data into Pods.
-            name: app-conf
-
- -

Ingress example

-
# Ingress 
-# https://kubernetes.io/docs/concepts/services-networking/ingress/
-apiVersion: extensions/v1beta1
-kind: Ingress
-metadata:
-  name: test
-  annotations:
-    ingress.kubernetes.io/rewrite-target: /
-    kubernetes.io/ingress.class: nginx      # Use the nginx-ingress Ingress controller
-spec:
-  tls:
-  - secretName: ingresssecret  # Referencing this secret in an Ingress will tell the Ingress controller to secure the channel from the client to the loadbalancer using TLS
-  rules:
-  - http:
-      paths:
-      - path: /api
-        backend:
-          serviceName: s1
-          servicePort: 80
----
-# Secure the Ingress by specifying a secret that contains a TLS private key and certificate. 
-apiVersion: v1
-data:
-  tls.crt: base64 encoded cert
-  tls.key: base64 encoded key
-kind: Secret
-metadata:
-  name: ingresssecret
-  namespace: default
-type: Opaque
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Minikube_Install_in_Ubuntu_on_Windows.md b/docs/Containers/Minikube_Install_in_Ubuntu_on_Windows.md similarity index 96% rename from docs_src/Containers/Minikube_Install_in_Ubuntu_on_Windows.md rename to docs/Containers/Minikube_Install_in_Ubuntu_on_Windows.md index 8a12716..2d3cdfa 100644 --- a/docs_src/Containers/Minikube_Install_in_Ubuntu_on_Windows.md +++ b/docs/Containers/Minikube_Install_in_Ubuntu_on_Windows.md @@ -10,7 +10,7 @@ cd ~ mkdir bin curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl chmod +x ./kubectl -# optionally +# optionally sudo mv ./kubectl /usr/local/bin/kubectl # then test kubectl get all @@ -25,7 +25,7 @@ echo "source <(kubectl completion bash)" >> ~/.bashrc sudo apt-get update && sudo apt-get install socat ``` -- In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using ``kube-up.sh`` or successfully deploy a Minikube cluster. +- In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using ``kube-up.sh`` or successfully deploy a Minikube cluster. Check that kubectl is properly configured by getting the cluster state: @@ -34,5 +34,3 @@ kubectl cluster-info ``` Beware that you may have two different config files in ``~/.kube/`` and ``/mnt/c/Users//.kube`` if you installed ``minikube`` in Windows. - - diff --git a/docs/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html b/docs/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html deleted file mode 100644 index 63ef95d..0000000 --- a/docs/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html +++ /dev/null @@ -1,1984 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Minikube Install in Ubuntu on Windows - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Minikube Install in Ubuntu on Windows

- -

Install kubectl in Ubuntu on Windows

-
cd ~
-mkdir bin
-curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
-chmod +x ./kubectl
-# optionally 
-sudo mv ./kubectl /usr/local/bin/kubectl
-# then test
-kubectl get all
-# enable autocompletion
-source <(kubectl completion bash)
-echo "source <(kubectl completion bash)" >> ~/.bashrc
-
- -
    -
  • If necessary, install socat
  • -
-
sudo apt-get update && sudo apt-get install socat
-
- -
    -
  • In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using kube-up.sh or successfully deploy a Minikube cluster.
  • -
-

Check that kubectl is properly configured by getting the cluster state:

-
kubectl cluster-info
-
- -

Beware that you may have two different config files in ~/.kube/ and /mnt/c/Users/<user name>/.kube if you installed minikube in Windows.

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Containers/Minikube_Install_on_Windows.md b/docs/Containers/Minikube_Install_on_Windows.md similarity index 88% rename from docs_src/Containers/Minikube_Install_on_Windows.md rename to docs/Containers/Minikube_Install_on_Windows.md index ea2c80f..5f6c5b6 100644 --- a/docs_src/Containers/Minikube_Install_on_Windows.md +++ b/docs/Containers/Minikube_Install_on_Windows.md @@ -8,17 +8,16 @@ tags: Kubernetes MiniKube Kubectl [Minikube]( https://kubernetes.io/docs/tasks/tools/install-minikube/ ) runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day. - For Windows, install [VirtualBox](https://www.virtualbox.org/wiki/Downloads) or Hyper-V first. -- Minikube is distributed in binary form: [ GitHub Repo ]( https://github.com/kubernetes/minikube/releases ). Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well. +- Minikube is distributed in binary form: [GitHub Repo]( https://github.com/kubernetes/minikube/releases ). Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well. - If needed, add ``C:\Program Files (x86)\Kubernetes\minikube`` or similar to the PATH (in ``System Settings`` > ``Environment Variables``) - Test that minikube works: ```shell -$ minikube +minikube ``` More info at [Getting Started]( https://kubernetes.io/docs/getting-started-guides/minikube/ ) - ## Install ``kubectl`` Use a version of [kubectl]( https://kubernetes.io/docs/tasks/tools/install-kubectl/ ) that is the same version as your server or later. Using an older ``kubectl`` with a newer server might produce validation errors. @@ -33,7 +32,7 @@ OR [Install Choco]( https://chocolatey.org/install ) -Then +Then ```shell choco install kubernetes-cli @@ -49,7 +48,7 @@ kubectl version Configure ``kubectl`` to use a remote Kubernetes cluster -- If ``~/.kube`` config does not exist (it should have been created by ``minikube``), enter the following in Powershell: +- If ``~/.kube`` config does not exist (it should have been created by ``minikube``), enter the following in Powershell: ```shell cd C:\users\ @@ -72,7 +71,7 @@ kubectl cluster-info echo "source <(kubectl completion bash)" >> ~/.bashrc ``` -- You must have appropriate permissions to list, create, edit and delete pods in your cluster: +- You must have appropriate permissions to list, create, edit and delete pods in your cluster: ```shell kubectl auth can-i list pods @@ -81,18 +80,17 @@ kubectl auth can-i edit pods kubectl auth can-i delete pods ``` -### Run ``kubectl`` from the Ubuntu on Windows command line +### Run ``kubectl`` from the Ubuntu on Windows command line If installed by ``choco`` ```shell export PATH=$PATH:/mnt/c/ProgramData/chocolatey/bin/kubectl -# then use: +# then use: kubectl.exe ``` - ## Run ``minikube`` [Running Kubernetes Locally via Minikube]( https://kubernetes.io/docs/getting-started-guides/minikube/ ) @@ -106,7 +104,7 @@ choco install curl - Test curl ```shell -curl http://google.com +curl https://google.com ``` - Start minikube @@ -114,6 +112,7 @@ curl http://google.com ```shell minikube start ``` + - List hosts ```shell @@ -130,8 +129,8 @@ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080 ```shell kubectl expose deployment hello-minikube --type=NodePort -``` - +``` + We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it via the exposed service. To check whether the pod is up and running we can use the following: @@ -166,7 +165,7 @@ Helm is a package manager for Kubernetes. Download a binary release of the Helm - Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step: ```shell -$ helm init +helm init ``` This will install Tiller (the helm server) into the current Kubernetes cluster (as listed in ``kubectl config current-context``). diff --git a/docs/Containers/Minikube_Install_on_Windows/index.html b/docs/Containers/Minikube_Install_on_Windows/index.html deleted file mode 100644 index 3c9dac7..0000000 --- a/docs/Containers/Minikube_Install_on_Windows/index.html +++ /dev/null @@ -1,2188 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Minikube Install on Windows - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Minikube Install on Windows

- -

Install minikube on Windows

-

Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.

-
    -
  • For Windows, install VirtualBox or Hyper-V first.
  • -
  • Minikube is distributed in binary form: GitHub Repo . Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well.
  • -
  • If needed, add C:\Program Files (x86)\Kubernetes\minikube or similar to the PATH (in System Settings > Environment Variables)
  • -
  • Test that minikube works:
  • -
-
$ minikube
-
- -

More info at Getting Started

-

Install kubectl

-

Use a version of kubectl that is the same version as your server or later. Using an older kubectl with a newer server might produce validation errors.

-

On Windows 10 (using Git Bash):

-
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/windows/amd64/kubectl.exe
-
- -

OR

-

Install Choco

-

Then

-
choco install kubernetes-cli
-
- -

Run kubectl version to verify that the version you’ve installed is sufficiently up-to-date.

-
kubectl version
-
- -

Configure kubectl

-

Configure kubectl to use a remote Kubernetes cluster

-
    -
  • If ~/.kube config does not exist (it should have been created by minikube), enter the following in Powershell:
  • -
-
cd C:\users\<yourusername>
-mkdir .kube
-cd .kube
-New-Item config -type file
-
- -
    -
  • -

    Edit the config file with a text editor of your choice.

    -
  • -
  • -

    Check that kubectl is properly configured by getting the cluster state:

    -
  • -
-
kubectl cluster-info
-
- -
    -
  • Enable auto-completion (if you use Git Bash)
  • -
-
echo "source <(kubectl completion bash)" >> ~/.bashrc
-
- -
    -
  • You must have appropriate permissions to list, create, edit and delete pods in your cluster:
  • -
-
kubectl auth can-i list pods
-kubectl auth can-i create pods
-kubectl auth can-i edit pods
-kubectl auth can-i delete pods
-
- -

Run kubectl from the Ubuntu on Windows command line

-

If installed by choco

-
export PATH=$PATH:/mnt/c/ProgramData/chocolatey/bin/kubectl
-
-# then use: 
-kubectl.exe
-
- -

Run minikube

-

Running Kubernetes Locally via Minikube

- -
choco install curl
-
- -
    -
  • Test curl
  • -
-
curl http://google.com 
-
- -
    -
  • Start minikube
  • -
-
minikube start
-
- -
    -
  • List hosts
  • -
-
kubectl get nodes
-
- -
    -
  • Test by deploying a container (creates a deployment / pod automatically)
  • -
-
kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080
-
- -
    -
  • Provide a dynamic port to the container (creates a service automatically)
  • -
-
kubectl expose deployment hello-minikube --type=NodePort
-
- -

We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it via the exposed service. -To check whether the pod is up and running we can use the following:

-
kubectl get pod
-
- -

Once the pod is running, curl it:

-
curl $(minikube service hello-minikube --url)
-
- -
    -
  • Cleanup:
  • -
-
kubectl delete deployment hello-minikube
-
- -
kubectl delete service hello-minikube
-
- -
minikube stop
-
- -

Install Helm

-

Helm is a package manager for Kubernetes. Download a binary release of the Helm client from here

-
    -
  • Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step:
  • -
-
$ helm init
-
- -

This will install Tiller (the helm server) into the current Kubernetes cluster (as listed in kubectl config current-context).

-
    -
  • Install a test Helm chart, then clean up
  • -
-
helm repo update              # Make sure we get the latest list of charts
-helm install stable/mysql
-helm ls
-helm status <release name>
-helm delete <release name>
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Data_Manipulation.md b/docs/Data_Science/Data_Manipulation.md similarity index 82% rename from docs_src/Data_Science/Data_Manipulation.md rename to docs/Data_Science/Data_Manipulation.md index 3fb3e8e..99f9335 100644 --- a/docs_src/Data_Science/Data_Manipulation.md +++ b/docs/Data_Science/Data_Manipulation.md @@ -7,20 +7,18 @@ tags: data ## Pandas * [Pandas cheatsheet](https://github.com/pandas-dev/pandas/blob/master/doc/cheatsheet/Pandas_Cheat_Sheet.pdf) -* [Pandas cheatsheet 2](http://www.datasciencecentral.com/profiles/blogs/data-science-in-python-pandas-cheat-sheet) - +* [Pandas cheatsheet 2](https://www.datasciencecentral.com/profiles/blogs/data-science-in-python-pandas-cheat-sheet) ## Data Wrangling with .NET [Quora: Which is the best machine learning library for .NET?](https://www.quora.com/Which-is-the-best-machine-learning-library-for-NET) -[Deedle- Exploratory data library for .NET](http://bluemountaincapital.github.io/Deedle/) +[Deedle- Exploratory data library for .NET](https://bluemountaincapital.github.io/Deedle/) Deedle is an easy to use library for data and time series manipulation and for scientific programming. It supports working with structured data frames, ordered and unordered data, as well as time series. Deedle is designed to work well for exploratory programming using F# and C# interactive console, but can be also used in efficient compiled .NET code. The library implements a wide range of operations for data manipulation including advanced indexing and slicing, joining and aligning data, handling of missing values, grouping and aggregation, statistics and more. -[Accord.NET Framework](http://accord-framework.net/) +[Accord.NET Framework](https://accord-framework.net/) Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET. - diff --git a/docs/Data_Science/Data_Manipulation/index.html b/docs/Data_Science/Data_Manipulation/index.html deleted file mode 100644 index d2d4ac4..0000000 --- a/docs/Data_Science/Data_Manipulation/index.html +++ /dev/null @@ -1,1982 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Data Manipulation - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Data Manipulation

- -

Pandas

- -

Data Wrangling with .NET

-

Quora: Which is the best machine learning library for .NET?

-

Deedle- Exploratory data library for .NET

-

Deedle is an easy to use library for data and time series manipulation and for scientific programming. It supports working with structured data frames, ordered and unordered data, as well as time series. Deedle is designed to work well for exploratory programming using F# and C# interactive console, but can be also used in efficient compiled .NET code.

-

The library implements a wide range of operations for data manipulation including advanced indexing and slicing, joining and aligning data, handling of missing values, grouping and aggregation, statistics and more.

-

Accord.NET Framework

-

Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET.

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Data_Visualization.md b/docs/Data_Science/Data_Visualization.md similarity index 61% rename from docs_src/Data_Science/Data_Visualization.md rename to docs/Data_Science/Data_Visualization.md index 56dafd6..6f997f2 100644 --- a/docs_src/Data_Science/Data_Visualization.md +++ b/docs/Data_Science/Data_Visualization.md @@ -6,42 +6,38 @@ tags: data ## Basics -[Data visualization - Wikipedia](http://en.wikipedia.org/wiki/Data_visualization) +[Data visualization - Wikipedia](https://en.wikipedia.org/wiki/Data_visualization) [19 Tools for Data Visualization Projects](https://www.upwork.com/hiring/data/19-data-visualization-tools/) -[22 free tools for data visualization and analysis - Computerworld](http://www.computerworld.com/s/article/9215504/22_free_tools_for_data_visualization_and_analysis) - -[22 free tools for data visualization and analysis](http://www.guardian.co.uk/news/datablog/2012/mar/28/data-visualisation-tools-free) +[22 free tools for data visualization and analysis - Computerworld](https://www.computerworld.com/s/article/9215504/22_free_tools_for_data_visualization_and_analysis) +[22 free tools for data visualization and analysis](https://www.guardian.co.uk/news/datablog/2012/mar/28/data-visualisation-tools-free) ### JavaScript libraries / APIs -[D3.js - Data-Driven Documents](http://d3js.org/) +[D3.js - Data-Driven Documents](https://d3js.org/) D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts. [D3 building blocks](https://bl.ocks.org/) -[C3.js](http://c3js.org/) +[C3.js](https://c3js.org/) [Google Charts](https://google-developers.appspot.com/chart/) - ## Tools [plot.ly](https://plot.ly/) [Tableau](https://public.tableau.com/s/) -[Qlik](http://www.qlikview.com/us) - -[Quadrigram](http://www.quadrigram.com/) +[Qlik](https://www.qlikview.com/us) +[Quadrigram](https://www.quadrigram.com/) ### Open-source data viz [Superset vs Metabase vs ReDash](https://hevodata.com/blog/superset-vs-metabase-vs-redash/ ) [AirPal]( https://airbnb.io/airpal/ ) - diff --git a/docs/Data_Science/Data_Visualization/index.html b/docs/Data_Science/Data_Visualization/index.html deleted file mode 100644 index e01ac24..0000000 --- a/docs/Data_Science/Data_Visualization/index.html +++ /dev/null @@ -1,2041 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Data Visualization - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Data Visualization

- -

Basics

-

Data visualization - Wikipedia

-

19 Tools for Data Visualization Projects

-

22 free tools for data visualization and analysis - Computerworld

-

22 free tools for data visualization and analysis

-

JavaScript libraries / APIs

-

D3.js - Data-Driven Documents

-

D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts.

-

D3 building blocks

-

C3.js

-

Google Charts

-

Tools

-

plot.ly

-

Tableau

-

Qlik

-

Quadrigram

-

Open-source data viz

-

Superset vs Metabase vs ReDash

-

AirPal

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Deep_Learning.md b/docs/Data_Science/Deep_Learning.md similarity index 50% rename from docs_src/Data_Science/Deep_Learning.md rename to docs/Data_Science/Deep_Learning.md index cf58712..2a2eee5 100644 --- a/docs_src/Data_Science/Deep_Learning.md +++ b/docs/Data_Science/Deep_Learning.md @@ -1,13 +1,12 @@ - -## Libraries +# Libraries - [DeepLearning4j]( https://deeplearning4j.org/quickstart ) - [TensorFlow]( https://www.tensorflow.org/ ) -- [Caffe - Deep Learning Framework]( http://caffe.berkeleyvision.org/ ) +- [Caffe - Deep Learning Framework]( https://caffe.berkeleyvision.org/ ) - [MXnet]( https://mxnet.apache.org/ ) - [Keras]( https://keras.io/ ) -## Useful Links +## Useful Links [What is deep learning]( https://www.quora.com/What-is-deep-learning ) @@ -15,28 +14,26 @@ [Deep Learning for beginners (deeplearning4j)]( https://deeplearning4j.org/deeplearningforbeginners.html ) -[The best answers to your most crucial deep learning questions]( http://www.bigdatanews.com/profiles/blogs/the-best-answers-to-your-most-crucial-deep-learning-questions ) +[The best answers to your most crucial deep learning questions]( https://www.bigdatanews.com/profiles/blogs/the-best-answers-to-your-most-crucial-deep-learning-questions ) -[Colah's blog - Neural Networks]( http://colah.github.io/ ) +[Colah's blog - Neural Networks]( https://colah.github.io/ ) [Neural Networks - Dropout]( https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf ) -[Deep Learning Glossary]( http://www.wildml.com/deep-learning-glossary/ ) +[Deep Learning Glossary]( https://www.wildml.com/deep-learning-glossary/ ) [Deep Learning for Visual Question Answering]( https://avisingh599.github.io/deeplearning/visual-qa/ ) ## Deep Learning - RNNs -[RNNs]( http://karpathy.github.io/2015/05/21/rnn-effectiveness/ ) +[RNNs]( https://karpathy.github.io/2015/05/21/rnn-effectiveness/ ) [Embed, encode, attend, predict- The new deep learning formula for state-of-the-art NLP models - Blog - Explosion AI]( https://explosion.ai/blog/deep-learning-formula-nlp ) -[RNN Tutorial Part 1]( http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/ ) - -[Part 2]( http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-2-implementing-a-language-model-rnn-with-python-numpy-and-theano/ ) - -[Part 3]( http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/ ) +[RNN Tutorial Part 1]( https://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/ ) -[Part 4]( http://www.wildml.com/2015/10/recurrent-neural-network-tutorial-part-4-implementing-a-grulstm-rnn-with-python-and-theano/ ) +[Part 2]( https://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-2-implementing-a-language-model-rnn-with-python-numpy-and-theano/ ) +[Part 3]( https://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/ ) +[Part 4]( https://www.wildml.com/2015/10/recurrent-neural-network-tutorial-part-4-implementing-a-grulstm-rnn-with-python-and-theano/ ) diff --git a/docs/Data_Science/Deep_Learning/index.html b/docs/Data_Science/Deep_Learning/index.html deleted file mode 100644 index 4dc3da0..0000000 --- a/docs/Data_Science/Deep_Learning/index.html +++ /dev/null @@ -1,2006 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Deep Learning - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - - -
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Dimensionality_Reduction.md b/docs/Data_Science/Dimensionality_Reduction.md similarity index 70% rename from docs_src/Data_Science/Dimensionality_Reduction.md rename to docs/Data_Science/Dimensionality_Reduction.md index f72dba0..5aad558 100644 --- a/docs_src/Data_Science/Dimensionality_Reduction.md +++ b/docs/Data_Science/Dimensionality_Reduction.md @@ -8,6 +8,6 @@ tags: data [Dimensionality Reduction]( https://en.wikipedia.org/wiki/Dimensionality_reduction ) -[Visualizing MNIST- An Exploration of Dimensionality Reduction - colah's blog]( http://colah.github.io/posts/2014-10-Visualizing-MNIST/ ) +[Visualizing MNIST- An Exploration of Dimensionality Reduction - colah's blog]( https://colah.github.io/posts/2014-10-Visualizing-MNIST/ ) -[Seven Techniques for Dimensionality Reduction: Missing Values, Low Variance Filter, High Correlation Filter, PCA, Random Forests, Backward Feature Elimination, and Forward Feature Construction ]( https://files.knime.com/sites/default/files/inline-images/knime_seventechniquesdatadimreduction.pdf ) +[Seven Techniques for Dimensionality Reduction: Missing Values, Low Variance Filter, High Correlation Filter, PCA, Random Forests, Backward Feature Elimination, and Forward Feature Construction]( https://files.knime.com/sites/default/files/inline-images/knime_seventechniquesdatadimreduction.pdf ) diff --git a/docs/Data_Science/Dimensionality_Reduction/index.html b/docs/Data_Science/Dimensionality_Reduction/index.html deleted file mode 100644 index b53bbf6..0000000 --- a/docs/Data_Science/Dimensionality_Reduction/index.html +++ /dev/null @@ -1,1960 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Dimensionality Reduction - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - - -
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Keras.md b/docs/Data_Science/Keras.md similarity index 78% rename from docs_src/Data_Science/Keras.md rename to docs/Data_Science/Keras.md index ed65546..d2a2c05 100644 --- a/docs_src/Data_Science/Keras.md +++ b/docs/Data_Science/Keras.md @@ -13,5 +13,5 @@ tags: deep learning - [manifold-learning-and-autoencoders](https://www.kaggle.com/apapiu/digit-recognizer/manifold-learning-and-autoencoders) - [Keras tutorial for Kaggle 2nd Annual Data Science Bowl](https://github.com/jocicmarko/kaggle-dsb2-keras/) -- [Supervised Sequence Labelling with Recurrent Neural Networks](http://www.cs.toronto.edu/~graves/preprint.pdf) -- [Sequence Classification with LSTM Recurrent Neural Networks in Python with Keras](http://machinelearningmastery.com/sequence-classification-lstm-recurrent-neural-networks-python-keras/) +- [Supervised Sequence Labelling with Recurrent Neural Networks](https://www.cs.toronto.edu/~graves/preprint.pdf) +- [Sequence Classification with LSTM Recurrent Neural Networks in Python with Keras](https://machinelearningmastery.com/sequence-classification-lstm-recurrent-neural-networks-python-keras/) diff --git a/docs/Data_Science/Keras/index.html b/docs/Data_Science/Keras/index.html deleted file mode 100644 index 22b9d13..0000000 --- a/docs/Data_Science/Keras/index.html +++ /dev/null @@ -1,1932 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Keras Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - - -
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Machine_Learning.md b/docs/Data_Science/Machine_Learning.md similarity index 59% rename from docs_src/Data_Science/Machine_Learning.md rename to docs/Data_Science/Machine_Learning.md index fa7fb3b..b148344 100644 --- a/docs_src/Data_Science/Machine_Learning.md +++ b/docs/Data_Science/Machine_Learning.md @@ -7,60 +7,60 @@ comments: true # Useful Links -[DataTau](http://www.datatau.com/) +[DataTau](https://www.datatau.com/) -# Datasets +## Datasets -- [UC Irvine Machine Learning Repository](http://archive.ics.uci.edu/ml/) +- [UC Irvine Machine Learning Repository](https://archive.ics.uci.edu/ml/) - [Quandl](https://www.quandl.com/) - [Kaggle](https://www.kaggle.com/) -# Algorithms +## Algorithms -## Restricted Boltzmann Machines +### Restricted Boltzmann Machines [A Beginner's Tutorial for Restricted Boltzmann Machines - Deeplearning4j- Open-source, Distributed Deep Learning for the JVM](https://deeplearning4j.org/restrictedboltzmannmachine) -## Embedding +### Embedding [t-distributed stochastic neighbor embedding - Wikipedia](https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding) -## Reinforcement Learning +### Reinforcement Learning [Lecture 10 Reinforcement Learning I](https://www.youtube.com/watch?v=IXuHxkpO5E8) -[PyBrain](http://www.pybrain.org/) +[PyBrain](https://www.pybrain.org/) -[PyBrain - a simple neural networks library in Python](http://fastml.com/pybrain-a-simple-neural-networks-library-in-python/) +[PyBrain - a simple neural networks library in Python](https://fastml.com/pybrain-a-simple-neural-networks-library-in-python/) [CyBrain](https://github.com/cgarciae/cybrain) -# ML Plaforms +## ML Plaforms -[Palladium](http://palladium.readthedocs.io/en/latest/) +[Palladium](https://palladium.readthedocs.io/en/latest/) -# GUI tools +## GUI tools -- [Orange](http://orange.biolab.si/) - - Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation +- [Orange](https://orange.biolab.si/) + - Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation together to create machine learning “programs”. Provides over 100 widgets for the environment and also provides a Python API and library for integrating into your application. - Weka explorer - - A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It + - A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It also provides an experimenter where you can perform the same tasks in a controlled environment and design a batch of algorithm runs that could run for an extended period of time and then review the results. Finally, it also provides a data flow interface where you can plug algorithms together like a flow diagram. Under the covers you can use Weka as a Java library and write programs that make use of the algorithms. - BigML - - A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for + - A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for configuring algorithms (decision trees) and reviewing the results. The best feature of this service is that it is all in the cloud, meaning that all you need is a web browser to get started. It also provides an API so that if you like it you can build an application around it. -# Tutorials +## Tutorials -- [machinelearningmastery.com](http://machinelearningmastery.com/) +- [machinelearningmastery.com](https://machinelearningmastery.com/) - [Kaggle](https://www.kaggle.com/wiki/Tutorials) -# Books +## Books -- [The Elements of Statistical Learning: Data Mining, Inference, and Prediction](http://statweb.stanford.edu/~tibs/ElemStatLearn/) -- [Boosting Foundations and Algorithms](http://mitpress.mit.edu/books/boosting) \ No newline at end of file +- [The Elements of Statistical Learning: Data Mining, Inference, and Prediction](https://statweb.stanford.edu/~tibs/ElemStatLearn/) +- [Boosting Foundations and Algorithms](https://mitpress.mit.edu/books/boosting) diff --git a/docs/Data_Science/Machine_Learning/index.html b/docs/Data_Science/Machine_Learning/index.html deleted file mode 100644 index b8d5c3f..0000000 --- a/docs/Data_Science/Machine_Learning/index.html +++ /dev/null @@ -1,1968 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Machine Learning - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Useful Links

-

DataTau

-

Datasets

- -

Algorithms

-

Restricted Boltzmann Machines

-

A Beginner's Tutorial for Restricted Boltzmann Machines - Deeplearning4j- Open-source, Distributed Deep Learning for the JVM

-

Embedding

-

t-distributed stochastic neighbor embedding - Wikipedia

-

Reinforcement Learning

-

Lecture 10 Reinforcement Learning I

-

PyBrain

-

PyBrain - a simple neural networks library in Python

-

CyBrain

-

ML Plaforms

-

Palladium

-

GUI tools

-
    -
  • Orange
      -
    • Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation -together to create machine learning “programs”. Provides over 100 widgets for the environment and also provides a Python API and library for -integrating into your application.
    • -
    -
  • -
  • Weka explorer
      -
    • A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It -also provides an experimenter where you can perform the same tasks in a controlled environment and design a batch of algorithm runs that could -run for an extended period of time and then review the results. Finally, it also provides a data flow interface where you can plug algorithms -together like a flow diagram. Under the covers you can use Weka as a Java library and write programs that make use of the algorithms.
    • -
    -
  • -
  • BigML
      -
    • A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for -configuring algorithms (decision trees) and reviewing the results. The best feature of this service is that it is all in the cloud, meaning that -all you need is a web browser to get started. It also provides an API so that if you like it you can build an application around it.
    • -
    -
  • -
-

Tutorials

- -

Books

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/Recommenders.md b/docs/Data_Science/Recommenders.md similarity index 99% rename from docs_src/Data_Science/Recommenders.md rename to docs/Data_Science/Recommenders.md index 0df5f27..f3a482e 100644 --- a/docs_src/Data_Science/Recommenders.md +++ b/docs/Data_Science/Recommenders.md @@ -7,8 +7,7 @@ tags: data ### Useful Links [Recommender System]( https://en.wikipedia.org/wiki/Recommender_system ) - + [Building a Recommendation Engine- An Algorithm Tutorial - Toptal]( https://www.toptal.com/algorithms/predicting-likes-inside-a-simple-recommendation-engine ) [Music Recognition Algorithm- How Shazam Works - Toptal]( https://www.toptal.com/algorithms/shazam-it-music-processing-fingerprinting-and-recognition ) - diff --git a/docs/Data_Science/Recommenders/index.html b/docs/Data_Science/Recommenders/index.html deleted file mode 100644 index aa5956f..0000000 --- a/docs/Data_Science/Recommenders/index.html +++ /dev/null @@ -1,1960 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Recommender Systems - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - - -
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Data_Science/scikit-learn.md b/docs/Data_Science/scikit-learn.md similarity index 100% rename from docs_src/Data_Science/scikit-learn.md rename to docs/Data_Science/scikit-learn.md diff --git a/docs/Data_Science/scikit-learn/index.html b/docs/Data_Science/scikit-learn/index.html deleted file mode 100644 index 8074377..0000000 --- a/docs/Data_Science/scikit-learn/index.html +++ /dev/null @@ -1,1958 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scikit-Learn - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Databases/Mongodb.md b/docs/Databases/Mongodb.md similarity index 81% rename from docs_src/Databases/Mongodb.md rename to docs/Databases/Mongodb.md index 36886ae..a71d294 100644 --- a/docs_src/Databases/Mongodb.md +++ b/docs/Databases/Mongodb.md @@ -24,26 +24,26 @@ myCursor.forEach(printjson); // or while (myCollection.hasNext()) { printjson(myCollection.next()); -} +} ``` ## Aggregation Tips ```js -// lowercase a string +// lowercase a string { $project: { "address": { $toLower: "$address" } } }, // extract field within embedded document { $project: { "experience.location": 1 } }, -// flatten +// flatten { $unwind: "$experience"}, { $group: { _id: "$_id", locs: { $push: { $ifNull: [ "$experience.location", "undefined" ] } } } } - + // output a collection { $out: "myCollection2" } -// get unique values +// get unique values { $group: { _id: "$fulladdress" } } ``` @@ -58,7 +58,7 @@ db = db.getSiblingDB("myDB"); // set current db for $out var myCollection = db.getCollection("myCollection"); // project if needed, get uniques if needed, create a new collection -myCollection.aggregate([{ $project:{ "fulladdress": 1 } },{ $group:{ _id: "$fulladdress" } },{ $out: "outputCollection" }], { allowDiskUse:true }); +myCollection.aggregate([{ $project:{ "fulladdress": 1 } },{ $group:{ _id: "$fulladdress" } },{ $out: "outputCollection" }], { allowDiskUse:true }); ``` - Or use bulk update: @@ -77,43 +77,43 @@ outputBulk.execute(); Add a count field to all records ```js -function gatherStats() { +function gatherStats() { var start = Date.now(); - + var inputDB = db.getSiblingDB("inputDB"); var inputColl = inputDB.getCollection("inputColl"); - // debug: inputColl.find( {} ).limit(2).forEach(printjson); + // debug: inputColl.find( {} ).limit(2).forEach(printjson); - outputDB = db.getSiblingDB("outputDB"); + outputDB = db.getSiblingDB("outputDB"); db = outputDB; // set current database for the next aggregate step // create temporary collection with count - inputColl.aggregate( [ - { $group: { _id: { $toLower: "$address" }, count: { $sum: 1 } } }, + inputColl.aggregate( [ + { $group: { _id: { $toLower: "$address" }, count: { $sum: 1 } } }, { $sort: { "count": -1 } }, - { $limit: 100000 }, // limit to 100k addresses with highest count + { $limit: 100000 }, // limit to 100k addresses with highest count { $out: "stats" } ], { allowDiskUse: true } ); // returns { _id, count } where _id is the address var statsColl = outputDB.getCollection("stats"); - + // create output collection - var outputColl = outputDB.getCollection("outputColl"); - var outputBulk = outputColl.initializeUnorderedBulkOp(); - var counter = 0; - - var inputCursor = inputColl.find( {}, {} ); - inputCursor.forEach( function(doc) { + var outputColl = outputDB.getCollection("outputColl"); + var outputBulk = outputColl.initializeUnorderedBulkOp(); + var counter = 0; + + var inputCursor = inputColl.find( {}, {} ); + inputCursor.forEach( function(doc) { var statDoc = statsColl.findOne( { _id: doc.address } ); if (statDoc) { doc.count = statDoc.count; outputBulk.insert(doc); - counter++; + counter++; if ( counter % 1000 == 0 ) { outputBulk.execute(); // you have to reset - outputBulk = outputColl.initializeUnorderedBulkOp(); + outputBulk = outputColl.initializeUnorderedBulkOp(); } } } @@ -124,8 +124,8 @@ function gatherStats() { // print the results - outputColl.find({}).sort({count: -1}).forEach(printjson); - + outputColl.find({}).sort({count: -1}).forEach(printjson); + var end = Date.now(); var duration = (end - start)/1000; printjson("Duration: " + duration + " seconds"); @@ -138,18 +138,18 @@ gatherStats(); Alternatively move data to memory: -```js - var statsDict = {}; // or better Object.create(null); +```js + var statsDict = {}; // or better Object.create(null); statsColl.find({}).forEach( function(doc) { statsDict[doc._id] = doc.count } ); - + // could also use: var statsArray = statsCursor.toArray(); - + inputCursor.forEach( function(doc) { if (doc.address in statsDict) - { - doc["count"] = statsDict[doc.address]; - outputBulk.insert(doc); + { + doc["count"] = statsDict[doc.address]; + outputBulk.insert(doc); } }); outputBulk.execute(); -``` \ No newline at end of file +``` diff --git a/docs/Databases/Mongodb/index.html b/docs/Databases/Mongodb/index.html deleted file mode 100644 index a123f15..0000000 --- a/docs/Databases/Mongodb/index.html +++ /dev/null @@ -1,2145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - MongoDB Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

MongoDB Cheatsheet

- -

Import from CSV

-
mongoimport --db users --collection contacts --type csv --headerline --file contacts.csv
-
- -

Specifying --headerline instructs mongoimport to determine the name of the fields using the first line in the CSV file. -Use the --ignoreBlanks option to ignore blank fields. For CSV and TSV imports, this option provides the desired functionality in most cases, because it avoids inserting fields with null values into your collection.

-

MongoImport documentation

- -
myCursor.forEach(printjson);
-
-// or
-while (myCollection.hasNext()) {
-   printjson(myCollection.next());
-} 
-
- -

Aggregation Tips

-
// lowercase a string 
-{ $project: { "address": { $toLower: "$address" } } },
-
-// extract field within embedded document
-{ $project: { "experience.location": 1 } },
-
-// flatten 
-{ $unwind: "$experience"},
-{ $group: { _id: "$_id", locs: { $push: { $ifNull: [ "$experience.location", "undefined" ] } } } }
-
-// output a collection
-{ $out: "myCollection2" }
-
-// get unique values 
-{ $group: { _id: "$fulladdress" } }
-
- -

Make a Copy

-

Don't use copyTo - it is fully blocking... and deprecated in 3.x

-
    -
  • Use the Aggregation framework:
  • -
-
db = db.getSiblingDB("myDB"); // set current db for $out
-var myCollection = db.getCollection("myCollection");
-
-// project if needed, get uniques if needed, create a new collection
-myCollection.aggregate([{ $project:{ "fulladdress": 1 } },{ $group:{ _id: "$fulladdress" } },{ $out: "outputCollection" }], { allowDiskUse:true }); 
-
- -
    -
  • Or use bulk update:
  • -
-
var outputColl = db.getCollection( "outputCollection" );
-var outputBulk = outputColl.initializeUnorderedBulkOp();
-myCollection.find( {}, { "fulladdress": 1 } ).forEach( function(doc) {
-     outputBulk.insert(doc);
-});
-outputBulk.execute();
-
- -

Longer Example

-

Add a count field to all records

-
function gatherStats() {   
-    var start = Date.now();
-
-    var inputDB = db.getSiblingDB("inputDB");
-    var inputColl = inputDB.getCollection("inputColl");
-
-    // debug: inputColl.find( {} ).limit(2).forEach(printjson);  
-
-    outputDB = db.getSiblingDB("outputDB"); 
-    db = outputDB; // set current database for the next aggregate step
-
-    // create temporary collection with count
-    inputColl.aggregate(  [ 
-    { $group: { _id: { $toLower: "$address" }, count: { $sum: 1 } } }, 
-    { $sort: { "count": -1 } },
-    { $limit: 100000 },                 // limit to 100k addresses with highest count  
-    { $out: "stats" }
-    ],  { allowDiskUse: true } );       // returns { _id, count } where _id is the address
-
-    var statsColl = outputDB.getCollection("stats");
-
-   // create output collection
-    var outputColl = outputDB.getCollection("outputColl"); 
-    var outputBulk = outputColl.initializeUnorderedBulkOp(); 
-    var counter = 0; 
-
-    var inputCursor = inputColl.find( {}, {} ); 
-    inputCursor.forEach( function(doc) { 
-        var statDoc = statsColl.findOne( { _id: doc.address } );
-        if (statDoc) {
-            doc.count = statDoc.count;
-            outputBulk.insert(doc);
-            counter++;  
-            if ( counter % 1000 == 0 ) {
-                    outputBulk.execute();
-                    // you have to reset
-                    outputBulk = outputColl.initializeUnorderedBulkOp(); 
-                }
-            }
-        }
-    );
-
-    if ( counter % 1000 > 0 )
-        outputBulk.execute();
-
-
-    // print the results
-    outputColl.find({}).sort({count: -1}).forEach(printjson); 
-
-    var end = Date.now();
-    var duration = (end - start)/1000;
-    printjson("Duration: " + duration + " seconds");
-
-    printjson(" | DONE | ");
-}
-
-gatherStats();
-
- -

Alternatively move data to memory:

-
    var statsDict = {}; // or better Object.create(null);    
-    statsColl.find({}).forEach( function(doc) { statsDict[doc._id] = doc.count } );
-
-    // could also use: var statsArray = statsCursor.toArray();
-
-    inputCursor.forEach( function(doc) {
-        if (doc.address in statsDict)
-        { 
-            doc["count"] = statsDict[doc.address]; 
-            outputBulk.insert(doc); 
-        }
-    });
-    outputBulk.execute();
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Databases/Redshift.md b/docs/Databases/Redshift.md similarity index 62% rename from docs_src/Databases/Redshift.md rename to docs/Databases/Redshift.md index 7db95c8..1afb2bd 100644 --- a/docs_src/Databases/Redshift.md +++ b/docs/Databases/Redshift.md @@ -8,12 +8,12 @@ tags: Redshift DW Warehouse - Smaller node types load data faster - Best Practices for data load: -+ 1 file in S3 per slice (instances in RedShift) -+ Compressed using gzip compression -+ File size: 1MB to 1GB compressed -+ COPY from S3 is the fastest -+ COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3 -+ First column of SORTKEY should not be compressed + - 1 file in S3 per slice (instances in RedShift) + - Compressed using gzip compression + - File size: 1MB to 1GB compressed + - COPY from S3 is the fastest + - COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3 + - First column of SORTKEY should not be compressed - Workflows: move from staging table to production table - Make sure to wrap the entire workflow into ONE transaction @@ -23,4 +23,3 @@ tags: Redshift DW Warehouse - Compress your staging tables - Do ANALYZE after VACUUM - diff --git a/docs/Databases/Redshift/index.html b/docs/Databases/Redshift/index.html deleted file mode 100644 index a701861..0000000 --- a/docs/Databases/Redshift/index.html +++ /dev/null @@ -1,1982 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - RedShift - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

RedShift

- -

Redshift Best Practices

-
    -
  • Smaller node types load data faster
  • -
  • Best Practices for data load:
  • -
  • 1 file in S3 per slice (instances in RedShift)
  • -
  • Compressed using gzip compression
  • -
  • File size: 1MB to 1GB compressed
  • -
  • COPY from S3 is the fastest
  • -
  • COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3
  • -
  • -

    First column of SORTKEY should not be compressed

    -
  • -
  • -

    Workflows: move from staging table to production table

    -
  • -
  • Make sure to wrap the entire workflow into ONE transaction
  • -
  • COMMITs are very expensive in RedShift
  • -
  • Disable statistics on staging tables
  • -
  • Make sure that the distribution keys match between staging and prod tables
  • -
  • -

    Compress your staging tables

    -
  • -
  • -

    Do ANALYZE after VACUUM

    -
  • -
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Databases/SQL.md b/docs/Databases/SQL.md similarity index 99% rename from docs_src/Databases/SQL.md rename to docs/Databases/SQL.md index 667df7b..4b9f0f3 100644 --- a/docs_src/Databases/SQL.md +++ b/docs/Databases/SQL.md @@ -3,6 +3,7 @@ title: SQL Cheatsheet category: databases tags: SQL RDBMS --- + # SQL Cheatsheet ## DML: SELECT diff --git a/docs/Databases/SQL/index.html b/docs/Databases/SQL/index.html deleted file mode 100644 index 3575236..0000000 --- a/docs/Databases/SQL/index.html +++ /dev/null @@ -1,3006 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - SQL Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

SQL Cheatsheet

-

DML: SELECT

-

Filter:

-
SELECT LastName, FirstName, Address FROM Persons
-WHERE Address IS NULL
-
- -

Like:

-
SELECT * FROM Customers
-WHERE City LIKE 's%';
-
-SELECT * FROM Customers
-WHERE Country LIKE '%land%';
-
-SELECT * FROM Customers
-WHERE Country NOT LIKE '%land%';
-
- -

Sort:

-
SELECT * FROM Customers
-ORDER BY Country DESC;
-
-SELECT * FROM Customers
-ORDER BY Country, CustomerName;
-
- -

Limit:

-
SELECT TOP number|percent column_name(s)
-FROM table_name;
-
--- Examples:
-SELECT TOP 2 * FROM Customers;
-
-SELECT TOP 50 PERCENT * FROM Customers;
-
- -

Oracle Syntax:

-
SELECT column_name(s)
-FROM table_name
-WHERE ROWNUM <= number;
-
- -

Joins:

-
SELECT Customers.CustomerName, Orders.OrderID
-FROM Customers
-FULL OUTER JOIN Orders
-ON Customers.CustomerID = Orders.CustomerID
-ORDER BY Customers.CustomerName;
-
- -

Union:

-
SELECT column_name(s) FROM table1
-UNION
-SELECT column_name(s) FROM table2;
-
-SELECT column_name(s) FROM table1
-UNION ALL
-SELECT column_name(s) FROM table2;
-
- -

Select Into:

-
SELECT column_name(s)
-INTO newtable [IN externaldb]
-FROM table1;
-
- -

Formula:

-
SELECT ProductName, UnitPrice*(UnitsInStock+ISNULL(UnitsOnOrder,0))
-FROM Products
-
- -

DML: INSERT

-
INSERT INTO table_name
-VALUES (value1,value2,value3,...);
-
-INSERT INTO table_name (column1,column2,column3,...)
-VALUES (value1,value2,value3,...);
-
--- Example:
-
-INSERT INTO Customers (CustomerName, City, Country)
-VALUES ('Cardinal', 'Stavanger', 'Norway');
-
- -

Insert from select:

-
INSERT INTO table2(column_name(s))
-SELECT column_name(s)
-FROM table1;
-
--- Example:
-
-INSERT INTO Customers (CustomerName, Country)
-SELECT SupplierName, Country FROM Suppliers
-WHERE Country='Germany';
-
- -

DML: UPDATE

-
UPDATE table_name
-SET column1=value1,column2=value2,...
-WHERE some_column=some_value;
-
--- Example:
-
-UPDATE Customers
-SET ContactName='Alfred Schmidt', City='Hamburg'
-WHERE CustomerName='Alfreds Futterkiste';
-
- -

DML: DELETE

-
DELETE FROM table_name
-WHERE some_column=some_value;
-
-DELETE FROM Customers
-WHERE CustomerName='Alfreds Futterkiste' AND ContactName='Maria Anders';
-
- -

Databases

-
CREATE DATABASE my_db;
-
-DROP DATABASE my_db;
-
- -

Tables

-

Create:

-
CREATE TABLE table_name
-(
-column_name1 data_type(size),
-column_name2 data_type(size),
-column_name3 data_type(size),
-....
-);
-
-CREATE TABLE table_name
-(
-column_name1 data_type(size) constraint_name,
-column_name2 data_type(size) constraint_name,
-column_name3 data_type(size) constraint_name,
-....
-);
-
- -

-- Examples

-
CREATE TABLE Persons
-(
-P_Id int NOT NULL UNIQUE,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255)
-)
-
-CREATE TABLE Persons
-(
-P_Id int NOT NULL,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255),
-CONSTRAINT uc_PersonID UNIQUE (P_Id, LastName)
-)
-
- -
ALTER TABLE Persons
-ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
-
-ALTER TABLE Persons
-DROP CONSTRAINT uc_PersonID
-
- -

Temporary Table:

-
CREATE TABLE #MyTempTable (cola INT PRIMARY KEY);
-INSERT INTO #MyTempTable VALUES (1);
-
- -

Drop / Truncate:

-
DROP TABLE table_name
-
-TRUNCATE TABLE table_name
-
- -

PRIMARY KEY constraint

-
CREATE TABLE Persons
-(
-P_Id int NOT NULL PRIMARY KEY,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255)
-)
-
-CREATE TABLE Persons
-(
-P_Id int NOT NULL,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255),
-CONSTRAINT PK_PersonID PRIMARY KEY (P_Id,LastName)
-)
-
-ALTER TABLE Persons
-ADD CONSTRAINT PK_PersonID PRIMARY KEY (P_Id,LastName)
-
-ALTER TABLE Persons
-DROP CONSTRAINT PK_PersonID
-
- -

FOREIGN KEY constraints

-
CREATE TABLE Orders
-(
-O_Id int NOT NULL PRIMARY KEY,
-OrderNo int NOT NULL,
-P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
-)
-
-CREATE TABLE Orders
-(
-O_Id int NOT NULL,
-OrderNo int NOT NULL,
-P_Id int,
-PRIMARY KEY (O_Id),
-CONSTRAINT FK_PerOrders FOREIGN KEY (P_Id)
-REFERENCES Persons(P_Id)
-)
-
- -
ALTER TABLE Orders
-ADD FOREIGN KEY (P_Id)
-REFERENCES Persons(P_Id)
-
-ALTER TABLE Orders
-ADD CONSTRAINT fk_PerOrders
-FOREIGN KEY (P_Id)
-REFERENCES Persons(P_Id)
-
-ALTER TABLE Orders
-DROP CONSTRAINT fk_PerOrders
-
- -

CHECK Constraints

-
CREATE TABLE Persons
-(
-P_Id int NOT NULL CHECK (P_Id>0),
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255)
-)
-
-CREATE TABLE Persons
-(
-P_Id int NOT NULL,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255),
-CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
-)
-
- -
ALTER TABLE Persons
-ADD CONSTRAINT CHK_Person CHECK (P_Id>0 AND City='Sandnes')
-
-ALTER TABLE Persons
-DROP CONSTRAINT CHK_Person
-
- -

DEFAULT Constraints

-
CREATE TABLE Orders
-(
-O_Id int NOT NULL,
-OrderNo int NOT NULL,
-P_Id int,
-OrderDate date DEFAULT GETDATE()
-)
-
- -
ALTER TABLE Persons
-ALTER COLUMN City SET DEFAULT 'SEATTLE'
-
-ALTER TABLE Persons
-ALTER COLUMN City DROP DEFAULT
-
- -

Index

-
CREATE UNIQUE INDEX index_name
-ON table_name (column_name)
-
-CREATE INDEX index_name
-ON table_name (column_name1, col_name2)
-
--- Example:
-
-CREATE INDEX PIndex
-ON Persons (LastName, FirstName)
-
- -
DROP INDEX table_name.index_name
-
--- Example:
-
-DROP INDEX IX_ProductVendor_BusinessEntityID
-    ON Purchasing.ProductVendor;
-
- -

Add / drop / alter column in table

-
ALTER TABLE table_name
-ADD column_name datatype
-
-ALTER TABLE table_name
-DROP COLUMN column_name
-
-ALTER TABLE table_name
-ALTER COLUMN column_name datatype
-
- -

Autoincrement

-
CREATE TABLE Persons
-(
-ID int IDENTITY(1,1) PRIMARY KEY,
-LastName varchar(255) NOT NULL,
-FirstName varchar(255),
-Address varchar(255),
-City varchar(255)
-)
-
- -

Example:

-
CREATE TABLE dbo.PurchaseOrderDetail
-(
-    PurchaseOrderID int NOT NULL
-        REFERENCES Purchasing.PurchaseOrderHeader(PurchaseOrderID),
-    LineNumber smallint NOT NULL,
-    ProductID int NULL
-        REFERENCES Production.Product(ProductID),
-    UnitPrice money NULL,
-    OrderQty smallint NULL,
-    ReceivedQty float NULL,
-    RejectedQty float NULL,
-    DueDate datetime NULL,
-    rowguid uniqueidentifier ROWGUIDCOL  NOT NULL
-        CONSTRAINT DF_PurchaseOrderDetail_rowguid DEFAULT (newid()),
-    ModifiedDate datetime NOT NULL
-        CONSTRAINT DF_PurchaseOrderDetail_ModifiedDate DEFAULT (getdate()),
-    LineTotal  AS ((UnitPrice*OrderQty)),
-    StockedQty  AS ((ReceivedQty-RejectedQty)),
-    CONSTRAINT PK_PurchaseOrderDetail_PurchaseOrderID_LineNumber
-              PRIMARY KEY CLUSTERED (PurchaseOrderID, LineNumber)
-              WITH (IGNORE_DUP_KEY = OFF)
-)
-ON PRIMARY;
-
- -

Views

-
CREATE VIEW view_name AS
-SELECT column_name(s)
-FROM table_name
-WHERE condition
-
- -
CREATE OR REPLACE VIEW view_name AS
-SELECT column_name(s)
-FROM table_name
-WHERE condition
-
- -
DROP VIEW view_name
-
- -

Examples:

-
CREATE VIEW [Products Above Average Price] AS
-SELECT ProductName,UnitPrice
-FROM Products
-WHERE UnitPrice > (SELECT AVG(UnitPrice) FROM Products)
-
-SELECT * FROM [Products Above Average Price]
-
- -
CREATE VIEW [Category Sales For 1997] AS
-SELECT DISTINCT CategoryName, Sum(ProductSales) AS CategorySales
-FROM [Product Sales for 1997]
-GROUP BY CategoryName
-
- -

Dates

-
GETDATE()  -- Returns the current date and time
-
-DATEPART() -- Returns a single part of a date/time
-
-DATEADD()  -- Adds or subtracts a specified time interval from a date
-
-DATEDIFF() -- Returns the time between two dates
-
-CONVERT()  -- Displays date/time data in different formats
-
- -

Example:

-
CREATE TABLE Orders
-(
-OrderId int NOT NULL PRIMARY KEY,
-ProductName varchar(50) NOT NULL,
-OrderDate datetime NOT NULL DEFAULT GETDATE()
-)
-
-SELECT DATEPART(yyyy,OrderDate) AS OrderYear,
-DATEPART(mm,OrderDate) AS OrderMonth,
-DATEPART(dd,OrderDate) AS OrderDay,
-FROM Orders
-WHERE OrderId=1
-
-SELECT OrderId,DATEADD(day,45,OrderDate) AS OrderPayDate
-FROM Orders
-
-SELECT DATEDIFF(day,'2008-06-05','2008-08-05') AS DiffDate
-
-CONVERT(VARCHAR(19),GETDATE())
-CONVERT(VARCHAR(10),GETDATE(),10)
-CONVERT(VARCHAR(10),GETDATE(),110)
-
- -

SQL Server Data Types

-

Data type / Description / Storage

-

char(n) -Fixed width character string. Maximum 8,000 characters -Defined width

-

varchar(n) -Variable width character string. Maximum 8,000 characters -2 bytes + number of chars

-

varchar(max) -Variable width character string. Maximum 1,073,741,824 characters -2 bytes + number of chars

-

text -Variable width character string. Maximum 2GB of text data -4 bytes + number of chars

-

nchar -Fixed width Unicode string. Maximum 4,000 characters -Defined width x 2

-

nvarchar -Variable width Unicode string. Maximum 4,000 characters

-

nvarchar(max) -Variable width Unicode string. Maximum 536,870,912 characters

-

ntext -Variable width Unicode string. Maximum 2GB of text data

-

bit -Allows 0, 1, or NULL

-

binary(n) -Fixed width binary string. Maximum 8,000 bytes

-

varbinary -Variable width binary string. Maximum 8,000 bytes

-

varbinary(max) -Variable width binary string. Maximum 2GB

-

image -Variable width binary string. Maximum 2GB

-

Number types

-

tinyint -Allows whole numbers from 0 to 255 -1 byte

-

smallint -Allows whole numbers between -32,768 and 32,767 -2 bytes

-

int -Allows whole numbers between -2,147,483,648 and 2,147,483,647 -4 bytes

-

bigint -Allows whole numbers between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 -8 bytes

-

decimal(p,s) -Fixed precision and scale numbers. -Allows numbers from -10^38 +1 to 10^38.

-

The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. -5-17 bytes

-

numeric(p,s) -Fixed precision and scale numbers. -Allows numbers from -10^38 +1 to 10^38.

-

The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. -5-17 bytes

-

smallmoney -Monetary data from -214,748.3648 to 214,748.3647 -4 bytes

-

money -Monetary data from -922,337,203,685,477.5808 to 922,337,203,685,477.5807 -8 bytes

-

float(n) -Floating precision number data from -1.79E + 308 to 1.79E + 308. -The n parameter indicates whether the field should hold 4 or 8 bytes. float(24) holds a 4-byte field and float(53) holds an 8-byte field. Default value of n is 53. -4 or 8 bytes

-

real -Floating precision number data from -3.40E + 38 to 3.40E + 38 -4 bytes

-

Date types

-

datetime -From January 1, 1753 to December 31, 9999 with an accuracy of 3.33 milliseconds -8 bytes

-

datetime2 -From January 1, 0001 to December 31, 9999 with an accuracy of 100 nanoseconds -6-8 bytes

-

smalldatetime -From January 1, 1900 to June 6, 2079 with an accuracy of 1 minute -4 bytes

-

date -Store a date only. From January 1, 0001 to December 31, 9999 -3 bytes

-

time -Store a time only to an accuracy of 100 nanoseconds -3-5 bytes

-

datetimeoffset -The same as datetime2 with the addition of a time zone offset -8-10 bytes

-

timestamp -Stores a unique number that gets updated every time a row gets created or modified. The timestamp value is based upon an internal clock and does not correspond to real time. Each table may have only one timestamp variable

-

Other data types

-

sql_variant -Stores up to 8,000 bytes of data of various data types, except text, ntext, and timestamp

-

uniqueidentifier -Stores a globally unique identifier (GUID)

-

xml -Stores XML formatted data. Maximum 2GB

-

cursor -Stores a reference to a cursor used for database operations

-

table -Stores a result-set for later processing

-

SQL Aggregate Functions

-

SQL aggregate functions return a single value, calculated from values in a column.

-

Useful aggregate functions:

-
    -
  • AVG() - Returns the average value
  • -
  • COUNT() - Returns the number of rows
  • -
  • TOP 1 - Single sample
  • -
  • MAX() - Returns the largest value
  • -
  • MIN() - Returns the smallest value
  • -
  • SUM() - Returns the sum
  • -
-

Examples:

-
SELECT COUNT(DISTINCT column_name) FROM table_name;
-
-SELECT TOP 1 column_name FROM table_name
-ORDER BY column_name DESC;
-
-SELECT column_name, aggregate_function(column_name)
-FROM table_name
-WHERE column_name operator value
-GROUP BY column_name;
-
-SELECT Shippers.ShipperName, COUNT(Orders.OrderID) AS NumberOfOrders
-FROM Orders
-LEFT JOIN Shippers
-ON Orders.ShipperID=Shippers.ShipperID
-GROUP BY ShipperName;
-
-SELECT column_name, aggregate_function(column_name)
-FROM table_name
-WHERE column_name operator value
-GROUP BY column_name
-HAVING aggregate_function(column_name) operator value;
-
-SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrders
-FROM Orders
-INNER JOIN Employees
-ON Orders.EmployeeID=Employees.EmployeeID)
-GROUP BY LastName
-HAVING COUNT(Orders.OrderID) > 10;
-
- -

SQL Scalar functions

-
    -
  • Converts a field to upper case: SELECT UPPER(column_name) FROM table_name;
  • -
  • Converts a field to lower case: SELECT LOWER(column_name) FROM table_name;
  • -
  • MID() - Extract characters from a text field
  • -
  • LEN() - Returns the length of a text field
  • -
  • ROUND() - Rounds a numeric field to the number of decimals specified
  • -
  • NOW() - Returns the current system date and time
  • -
  • FORMAT() - Formats how a field is to be displayed
  • -
-
SELECT ProductName, ROUND(Price,0) AS RoundedPrice
-FROM Products;
-
- -

Variables

-
DECLARE @myvar char(20);
-SET @myvar = 'This is a test';
-SELECT @myvar;
-
- -

Scalar Function

-
CREATE FUNCTION FunctionName
-(
--- Add the parameters for the function here
-@p1 int
-)
-RETURNS int
-AS
-BEGIN
--- Declare the return variable here
-DECLARE @Result int
--- Add the T-SQL statements to compute the return value here
-SELECT @Result = @p1
-
--- Return the result of the function
-RETURN @Result
-END
-
- -

Table Value Function

-
IF OBJECT_ID (N'dbo.EmployeeByID' ) IS NOT NULL
-   DROP FUNCTION dbo.EmployeeByID
-GO
-
-CREATE FUNCTION dbo.EmployeeByID(@InEmpID int)
-RETURNS @retFindReports TABLE
-(
-    -- columns returned by the function
-    EmployeeID int NOT NULL,
-    Name nvarchar(255 ) NOT NULL,
-    Title nvarchar(50 ) NOT NULL,
-    EmployeeLevel int NOT NULL
-)
-AS
--- body of the function
-BEGIN
-   WITH DirectReports(Name , Title , EmployeeID , EmployeeLevel , Sort ) AS
-    (SELECT CONVERT( varchar(255 ), c .FirstName + ' ' + c.LastName ),
-        e.Title ,
-        e.EmployeeID ,
-        1 ,
-        CONVERT(varchar (255), c. FirstName + ' ' + c .LastName)
-     FROM HumanResources.Employee AS e
-          JOIN Person.Contact AS c ON e.ContactID = c.ContactID
-     WHERE e.EmployeeID = @InEmpID
-   UNION ALL
-     SELECT CONVERT (varchar( 255), REPLICATE ( '| ' , EmployeeLevel) +
-        c.FirstName + ' ' + c. LastName),
-        e.Title ,
-        e.EmployeeID ,
-        EmployeeLevel + 1,
-        CONVERT ( varchar(255 ), RTRIM (Sort) + '| ' + FirstName + ' ' +
-                 LastName)
-     FROM HumanResources.Employee as e
-          JOIN Person.Contact AS c ON e.ContactID = c.ContactID
-          JOIN DirectReports AS d ON e. ManagerID = d. EmployeeID
-    )
-   -- copy the required columns to the result of the function
-
-   INSERT @retFindReports
-   SELECT EmployeeID, Name, Title, EmployeeLevel
-     FROM DirectReports
-   ORDER BY Sort
-   RETURN
-END
-GO
-
- -

Stored Procedure

-
CREATE PROCEDURE ProcedureName
-        -- Add the parameters for the stored procedure here
-        @p1 int = 0 ,
-        @p2 int = 0
-AS
-BEGIN
-        -- SET NOCOUNT ON added to prevent extra result sets from
-        -- interfering with SELECT statements.
-        SET NOCOUNT ON;
-
-    -- Insert statements for procedure here
-        SELECT @p1 , @p2
-END
-GO
-
- -

Self-join

-

Q. Here's the data in a table 'orders'

-
customer_id order_id order_day
-123        27424624    25Dec2011
-123        89690900    25Dec2010
-797        12131323    25Dec2010
-876        67145419    15Dec2011
-
- -

Could you give me SQL for customers who placed orders on both the days, 25th Dec 2010 and 25th Dec 2011?

-
    SELECT o.customer_id, o.order_day
-    FROM orders AS o
-    INNER JOIN orders AS o1
-    ON o.customer_id = o1.customer_id
-    WHERE ...
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/DevOps/CloudFormation.md b/docs/DevOps/CloudFormation.md similarity index 77% rename from docs_src/DevOps/CloudFormation.md rename to docs/DevOps/CloudFormation.md index d8ca400..e0c879f 100644 --- a/docs_src/DevOps/CloudFormation.md +++ b/docs/DevOps/CloudFormation.md @@ -8,17 +8,15 @@ tags: AWS [Why we use Terraform and not Chef, Puppet, Ansible, SaltStack, or CloudFormation](https://blog.gruntwork.io/why-we-use-terraform-and-not-chef-puppet-ansible-saltstack-or-cloudformation-7989dad2865c#.sp4ce0kog) - ## Tools -- [AWS CLI cloudformation](http://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html#cli-aws-cloudformation) - - [aws cloudformation validate-template](http://docs.aws.amazon.com/cli/latest/reference/cloudformation/validate-template.html) -- [boto3 cloudformation](http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html) - +- [AWS CLI cloudformation](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html#cli-aws-cloudformation) + - [aws cloudformation validate-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/validate-template.html) +- [boto3 cloudformation](https://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html) ## [YAML](https://en.wikipedia.org/wiki/YAML) -- [YAML Cheatsheet](http://lzone.de/cheat-sheet/YAML) +- [YAML Cheatsheet](https://lzone.de/cheat-sheet/YAML) - [YAML Cheatsheet 2](https://gist.github.com/anonymous/1486924) YAML notation for folded text: `>` @@ -36,9 +34,10 @@ data: > ## Sample Templates -[Templates for the US East (Northern Virginia) Region](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-sample-templates-us-east-1.html) +[Templates for the US East (Northern Virginia) Region](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-sample-templates-us-east-1.html) [AWSlabs on GitHub](https://github.com/awslabs) + - [Startup kit templates](https://github.com/awslabs/startup-kit-templates) - [AWS CloudFormation Sample Templates](https://github.com/awslabs/aws-cloudformation-templates) @@ -48,12 +47,11 @@ data: > [Deploying Microservices with Amazon ECS, AWS CloudFormation, and an Application Load Balancer](https://github.com/awslabs/ecs-refarch-cloudformation) - ## Template Basics -[Template Basics](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html) +[Template Basics](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html) -[Template Anatomy](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html) +[Template Anatomy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html) ```yaml --- @@ -98,14 +96,14 @@ Description: > Metadata: Instances: Description: "Information about the instances" - Databases: + Databases: Description: "Information about the databases" -Parameters: - InstanceTypeParameter: +Parameters: + InstanceTypeParameter: Type: String # String, Number, List, CommaDelimitedList e.g. "test,dev,prod", or an AWS-specific types such as Amazon EC2 key pair names and VPC IDs. Default: t2.micro - AllowedValues: + AllowedValues: - t2.micro - m1.small Description: Enter t2.micro or m1.small. Default is t2.micro. @@ -114,23 +112,23 @@ Parameters: # MinLength: 2 # for String # MaxLength: 10 # MinValue: 0 # for Number types. - # MaxValue: 100 + # MaxValue: 100 # NoEcho: True -Mappings: - RegionMap: - us-east-1: +Mappings: + RegionMap: + us-east-1: "32": "ami-6411e20d" - us-west-1: + us-west-1: "32": "ami-c9c7978c" - eu-west-1: + eu-west-1: "32": "ami-37c2f643" - ap-southeast-1: + ap-southeast-1: "32": "ami-66f28c34" - ap-northeast-1: + ap-northeast-1: "32": "ami-9c03a89d" -Conditions: +Conditions: CreateProdResources: !Equals [ !Ref EnvType, prod ] Transform: @@ -144,10 +142,10 @@ Resources: Ref: InstanceTypeParameter # reference to parameter above ImageId: ami-2f726546 -Outputs: - VolumeId: +Outputs: + VolumeId: Condition: CreateProdResources - Value: + Value: !Ref NewVolume ``` @@ -182,5 +180,5 @@ Resources: - IpProtocol: tcp FromPort: '22' ToPort: '22' - CidrIp: 0.0.0.0/0 -``` \ No newline at end of file + CidrIp: 0.0.0.0/0 +``` diff --git a/docs/DevOps/CloudFormation/index.html b/docs/DevOps/CloudFormation/index.html deleted file mode 100644 index 2303088..0000000 --- a/docs/DevOps/CloudFormation/index.html +++ /dev/null @@ -1,2223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - CloudFormation Basics - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

CloudFormation Basics

- -

DevOps Philosophy

-

Why we use Terraform and not Chef, Puppet, Ansible, SaltStack, or CloudFormation

-

Tools

- -

YAML

- -

YAML notation for folded text: >

-
data: >
-   Wrapped text
-   will be folded
-   into a single
-   paragraph
-
-   Blank lines denote
-   paragraph breaks
-
- -

Sample Templates

-

Templates for the US East (Northern Virginia) Region

-

AWSlabs on GitHub -- Startup kit templates -- AWS CloudFormation Sample Templates

-

Cloudonaut Templates

-

Free Templates for AWS CloudFormation (Cloudonaut)

-

Deploying Microservices with Amazon ECS, AWS CloudFormation, and an Application Load Balancer

-

Template Basics

-

Template Basics

-

Template Anatomy

-
---
-AWSTemplateFormatVersion: "version date"
-
-Description:
-  String
-
-Metadata:
-  template metadata
-
-Parameters:
-  set of parameters
-
-Mappings:
-  set of mappings
-
-Conditions:
-  set of conditions
-
-Transform:
-  set of transforms
-
-Resources:
-  set of resources
-
-Outputs:
-  set of outputs
-
- -

With examples:

-
---
-AWSTemplateFormatVersion: "2010-09-09"
-
-Description: >
-  Here are some
-  details about
-  the template.
-
-Metadata:
-  Instances:
-    Description: "Information about the instances"
-  Databases: 
-    Description: "Information about the databases"
-
-Parameters: 
-  InstanceTypeParameter: 
-    Type: String            # String, Number, List<Number>, CommaDelimitedList e.g. "test,dev,prod", or an AWS-specific types such as Amazon EC2 key pair names and VPC IDs.
-    Default: t2.micro
-    AllowedValues: 
-      - t2.micro
-      - m1.small
-    Description: Enter t2.micro or m1.small. Default is t2.micro.
-    # AllowedPattern: "[A-Za-z0-9]+" # A regular expression that represents the patterns you want to allow for String types.
-    # ConstraintDescription: Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+
-    # MinLength: 2  # for String
-    # MaxLength: 10
-    # MinValue: 0   # for Number types.
-    # MaxValue: 100 
-    # NoEcho: True
-
-Mappings: 
-  RegionMap: 
-    us-east-1: 
-      "32": "ami-6411e20d"
-    us-west-1: 
-      "32": "ami-c9c7978c"
-    eu-west-1: 
-      "32": "ami-37c2f643"
-    ap-southeast-1: 
-      "32": "ami-66f28c34"
-    ap-northeast-1: 
-      "32": "ami-9c03a89d"
-
-Conditions: 
-  CreateProdResources: !Equals [ !Ref EnvType, prod ]
-
-Transform:
-  set of transforms
-
-Resources:
-  Ec2Instance:
-      Type: AWS::EC2::Instance
-      Properties:
-        InstanceType:
-          Ref: InstanceTypeParameter  # reference to parameter above
-        ImageId: ami-2f726546
-
-Outputs: 
-  VolumeId: 
-    Condition: CreateProdResources
-    Value: 
-      !Ref NewVolume
-
- -
    -
  • The Ref function can refer to input parameters that are specified at stack creation time.
  • -
-

Examples

-

S3

-
Resources:
-  HelloBucket:
-    Type: AWS::S3::Bucket  # AWS::ProductIdentifier::ResourceType
-
- -

EC2

-
Resources:
-  Ec2Instance:
-    Type: AWS::EC2::Instance
-    Properties:
-      SecurityGroups:
-      - Ref: InstanceSecurityGroup
-      KeyName: mykey
-      ImageId: ''
-  InstanceSecurityGroup:
-    Type: AWS::EC2::SecurityGroup
-    Properties:
-      GroupDescription: Enable SSH access via port 22
-      SecurityGroupIngress:
-      - IpProtocol: tcp
-        FromPort: '22'
-        ToPort: '22'
-        CidrIp: 0.0.0.0/0    
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/DevOps/Git.md b/docs/DevOps/Git.md similarity index 65% rename from docs_src/DevOps/Git.md rename to docs/DevOps/Git.md index f406961..eccdde4 100644 --- a/docs_src/DevOps/Git.md +++ b/docs/DevOps/Git.md @@ -6,117 +6,117 @@ tags: SCM DevOps # Git Cheatsheets -* [Graphical git cheatsheet](http://byte.kde.org/~zrusin/git/git-cheat-sheet-medium.png) +* [Graphical git cheatsheet](https://byte.kde.org/~zrusin/git/git-cheat-sheet-medium.png) * [Git basic commands](https://www.atlassian.com/git/tutorials/svn-to-git-prepping-your-team-migration/basic-git-commands) * [Git cheatsheet (visual)](https://www.maxoberberger.net/media/cheatsheet/git-cheatsheet-visual.pdf) -* [Git cheatsheet (interactive)](http://ndpsoftware.com/git-cheatsheet.html#loc=workspace) +* [Git cheatsheet (interactive)](https://ndpsoftware.com/git-cheatsheet.html#loc=workspace) * [Git full documentation](https://git-scm.com/doc) *Repo hosting:* -* [BitBucket](https://bitbucket.org/) -* [GitHub](https://github.com/) +* [BitBucket](https://bitbucket.org/) +* [GitHub](https://github.com/) ## Common Commands -- Create a new Git repository in current directory: +* Create a new Git repository in current directory: ```bash git init ``` -- Or create an empty Git repository in the specified directory: +* Or create an empty Git repository in the specified directory: ```bash git init ``` -- Or copy an existing Git repository: +* Or copy an existing Git repository: ```bash git clone ``` -- Clone the repository located at into the folder called on the local machine: +* Clone the repository located at `` into the folder called `` on the local machine: ```bash git clone git clone username@host:/path/to/repository ``` -- Global Configuration: +* Global Configuration: ```bash -$ git config --global user.name "Firstname Lastname" -$ git config --global user.email "your_email@youremail.com" +git config --global user.name "Firstname Lastname" +git config --global user.email "your_email@youremail.com" ``` -- Stage all changes in `` for the next commit: +* Stage all changes in `` for the next commit: ```bash git add ``` -- Or stage all changes in `` for the next commit: +* Or stage all changes in `` for the next commit: ```bash git add # usually '.' for current directory ``` -- Commit the staged snapshot to the project history: +* Commit the staged snapshot to the project history: ```bash -git commit # interactive +git commit # interactive git commit -m "" ``` -- Or add and commit all in one: +* Or add and commit all in one: ```bash git commit -am "message" ``` -- Fix up the most recent commit (don't do that if shared history): +* Fix up the most recent commit (don't do that if shared history): ```bash git commit --amend ``` -- List which files are staged, unstaged, and untracked: +* List which files are staged, unstaged, and untracked: ```bash git status git status -s # short format ``` -- Show file diff: +* Show file diff: ```bash git diff # git diff by itself doesn’t show all changes made since your last commit – only changes that are still unstaged. git diff --staged # Shows file differences between staging and the last file version ``` -- Open GUI: +* Open GUI: ```bash git gui ``` -- Displays committed snapshots: +* Displays committed snapshots: ```bash git log -n git log --graph --decorate --oneline ``` -- Checking out commits, and checking out branches: +* Checking out commits, and checking out branches: ```bash git checkout # Return to commit git checkout master # Return to the master branch (or whatever branch we choose) ``` -- Check out a previous version of a file: +* Check out a previous version of a file: ```bash git checkout # Check out the version of the file from the selected commit @@ -127,13 +127,13 @@ git checkout HEAD hello.py # Check out the most recent version Branches are just pointers to commits. -- List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch): +* List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch): ```bash git branch ``` -- Create a new branch called ````. +* Create a new branch called ````. ```bash git branch @@ -151,19 +151,19 @@ Or direcly create-and-check out ````. git checkout -b ``` -- Safe delete the branch: +* Safe delete the branch: -``` +```bash git branch -d ``` -- Merge the specified branch into the current branch: +* Merge the specified branch into the current branch: ```bash git merge ``` -- Undo any undesired changes +* Undo any undesired changes Generate a new commit that undoes all of the changes introduced in ````, then apply it to the current branch @@ -173,44 +173,44 @@ git revert ``git revert`` undoes a single commit — it does not “revert” back to the previous state of a project by removing all subsequent commits. -- Reset (dangerous method - erases history): +* Reset (dangerous method - erases history): ```bash git reset ``` -- List the remote connections you have to other repositories. +* List the remote connections you have to other repositories. ```bash git remote -v ``` -- Create a new connection / delete a connection to a remote repository. +* Create a new connection / delete a connection to a remote repository. ```bash git remote add # often "origin" git remote rm # delete ``` -- Fetch the specified remote’s copy of the current branch and immediately merge it into the local copy. This is the same as ``git fetch `` followed by ``git merge origin/``. +* Fetch the specified remote’s copy of the current branch and immediately merge it into the local copy. This is the same as ``git fetch `` followed by ``git merge origin/``. ```bash git pull ``` -- Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits. +* Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits. ```bash git pull --rebase ``` -- Transfer commits from your local repository to a remote repo. +* Transfer commits from your local repository to a remote repo. ```bash git push ``` -- Pushes the current branch to the remote server and links the local branch to the remote so next time you can do ``git pull`` or ``git push``. +* Pushes the current branch to the remote server and links the local branch to the remote so next time you can do ``git pull`` or ``git push``. ```bash git push -u origin @@ -221,32 +221,32 @@ git push -u origin ### Clone a Repo ```bash -$ mkdir repos -$ cd ~/repos -$ git clone https:// -$ ls -al +mkdir repos +cd ~/repos +git clone https:// +ls -al ``` ### Add a change in the working directory to the staging area ```bash -$ git status -$ git add README +git status +git add README ``` ``-A``, ``--all`` finds new files as well as staging modified content and removing files that are no longer in the working tree. ```bash -$ git add -A -$ git commit -m "Add repo instructions" -$ git push -u origin master -$ git pull -$ ssh -p 2222 user@domain.com +git add -A +git commit -m "Add repo instructions" +git push -u origin master +git pull +ssh -p 2222 user@domain.com ``` -### Short-lived topic branches +### Short-lived topic branches -* Start a new feature: +* Start a new feature: ```bash git checkout -b new-feature master @@ -302,7 +302,7 @@ git push origin master The ``--bare`` flag creates a repository that doesn’t have a working directory, making it impossible to edit files and commit changes in that repository. Central repositories should always be created as bare repositories because pushing branches to a non-bare repository has the potential to overwrite changes. ```bash -$ git init --bare foobar.git -$ git rev-parse --show-toplevel # print top-level directory -$ git rev-parse --git-dir # print .git directory name +git init --bare foobar.git +git rev-parse --show-toplevel # print top-level directory +git rev-parse --git-dir # print .git directory name ``` diff --git a/docs/DevOps/Git/index.html b/docs/DevOps/Git/index.html deleted file mode 100644 index 7636d5d..0000000 --- a/docs/DevOps/Git/index.html +++ /dev/null @@ -1,2359 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Git Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Git Cheatsheets

- -

Repo hosting: -* BitBucket -* GitHub

-

Common Commands

-
    -
  • Create a new Git repository in current directory:
  • -
-
git init
-
- -
    -
  • Or create an empty Git repository in the specified directory:
  • -
-
git init <directory>
-
- -
    -
  • Or copy an existing Git repository:
  • -
-
git clone <repo URL>
-
- -
    -
  • Clone the repository located at into the folder called on the local machine:
  • -
-
git clone <repo> <directory>
-git clone username@host:/path/to/repository
-
- -
    -
  • Global Configuration:
  • -
-
$ git config --global user.name "Firstname Lastname"
-$ git config --global user.email "your_email@youremail.com"
-
- -
    -
  • Stage all changes in <file> for the next commit:
  • -
-
git add <file>
-
- -
    -
  • Or stage all changes in <directory> for the next commit:
  • -
-
git add <directory>  # usually '.' for current directory
-
- -
    -
  • Commit the staged snapshot to the project history:
  • -
-
git commit  # interactive   
-git commit -m "<message>"
-
- -
    -
  • Or add and commit all in one:
  • -
-
git commit -am "message"
-
- -
    -
  • Fix up the most recent commit (don't do that if shared history):
  • -
-
git commit --amend
-
- -
    -
  • List which files are staged, unstaged, and untracked:
  • -
-
git status
-git status -s  # short format
-
- -
    -
  • Show file diff:
  • -
-
git diff           #  git diff by itself doesn’t show all changes made since your last commit – only changes that are still unstaged.
-git diff --staged  #  Shows file differences between staging and the last file version
-
- -
    -
  • Open GUI:
  • -
-
git gui
-
- -
    -
  • Displays committed snapshots:
  • -
-
git log -n <limit>
-git log --graph --decorate --oneline
-
- -
    -
  • Checking out commits, and checking out branches:
  • -
-
git checkout <commit>       #  Return to commit
-git checkout master         #  Return to the master branch (or whatever branch we choose)
-
- -
    -
  • Check out a previous version of a file:
  • -
-
git checkout <commit> <file>    #  Check out the version of the file from the selected commit
-git checkout HEAD hello.py      #  Check out the most recent version
-
- -

Branches

-

Branches are just pointers to commits.

-
    -
  • List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch):
  • -
-
git branch
-
- -
    -
  • Create a new branch called <branch>.
  • -
-
git branch <branch>
-
- -

This does not check out the new branch. You need:

-
git checkout <existing-branch>
-
- -

Or direcly create-and-check out <new-branch>.

-
git checkout -b <new-branch>
-
- -
    -
  • Safe delete the branch:
  • -
-
git branch -d <branch>
-
- -
    -
  • Merge the specified branch into the current branch:
  • -
-
git merge <branch>
-
- -
    -
  • Undo any undesired changes
  • -
-

Generate a new commit that undoes all of the changes introduced in <commit>, then apply it to the current branch

-
git revert <commit>
-
- -

git revert undoes a single commit — it does not “revert” back to the previous state of a project by removing all subsequent commits.

-
    -
  • Reset (dangerous method - erases history):
  • -
-
git reset
-
- -
    -
  • List the remote connections you have to other repositories.
  • -
-
git remote -v
-
- -
    -
  • Create a new connection / delete a connection to a remote repository.
  • -
-
git remote add <name> <url>  # often "origin"
-git remote rm <name>         # delete
-
- -
    -
  • Fetch the specified remote’s copy of the current branch and immediately merge it into the local copy. This is the same as git fetch <remote> followed by git merge origin/<current-branch>.
  • -
-
git pull <remote>
-
- -
    -
  • Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits.
  • -
-
git pull --rebase <remote>
-
- -
    -
  • Transfer commits from your local repository to a remote repo.
  • -
-
git push <remote> <branch>
-
- -
    -
  • Pushes the current branch to the remote server and links the local branch to the remote so next time you can do git pull or git push.
  • -
-
git push -u origin <branch>
-
- -

Typical Workflows

-

Clone a Repo

-
$ mkdir repos
-$ cd ~/repos
-$ git clone https://<url>
-$ ls -al  <repo dir>
-
- -

Add a change in the working directory to the staging area

-
$ git status
-$ git add README
-
- -

-A, --all finds new files as well as staging modified content and removing files that are no longer in the working tree.

-
$ git add -A
-$ git commit -m "Add repo instructions"
-$ git push -u origin master
-$ git pull
-$ ssh -p 2222 user@domain.com
-
- -

Short-lived topic branches

-
    -
  • Start a new feature:
  • -
-
git checkout -b new-feature master
-
- -
    -
  • Edit some files:
  • -
-
git add <file>
-git commit -m "Start a feature"
-
- -
    -
  • Edit some files
  • -
-
git add <file>
-git commit -m "Finish a feature"
-
- -
    -
  • Merge in the new-feature branch
  • -
-
git checkout master
-git merge new-feature
-git branch -d new-feature
-
- -

Push and pull from a centralized repo

-
    -
  • To push the master branch to the central repo:
  • -
-
git push origin master
-
- -

If local history has diverged from the central repository, Git will refuse the request.

-
git pull --rebase origin master
-
- -

Sync my local repo with the remote repo

-
git pull origin master
-git add filename.xyz
-git commit . -m “comment”
-git push origin master
-
- -

Create a central Repo

-

The --bare flag creates a repository that doesn’t have a working directory, making it impossible to edit files and commit changes in that repository. Central repositories should always be created as bare repositories because pushing branches to a non-bare repository has the potential to overwrite changes.

-
$ git init --bare foobar.git  
-$ git rev-parse --show-toplevel     # print top-level directory
-$ git rev-parse --git-dir           # print .git directory name
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/DevOps/Orchestrator_Scheduler.md b/docs/DevOps/Orchestrator_Scheduler.md similarity index 66% rename from docs_src/DevOps/Orchestrator_Scheduler.md rename to docs/DevOps/Orchestrator_Scheduler.md index 0e4b8ac..fbeef34 100644 --- a/docs_src/DevOps/Orchestrator_Scheduler.md +++ b/docs/DevOps/Orchestrator_Scheduler.md @@ -9,12 +9,12 @@ Tools to build complex pipelines of batch jobs. They handle dependency resolutio ### Links -[Luigi vs Airflow vs Pinball]( http://bytepawn.com/luigi-airflow-pinball.html ) +[Luigi vs Airflow vs Pinball]( https://bytepawn.com/luigi-airflow-pinball.html ) [Airflow Documentation](https://airflow.incubator.apache.org/) [Luigi]( https://github.com/spotify/luigi ) -[Petabyte-Scale Data Pipelines with Docker, Luigi and Elastic Spot Instances]( http://tech.adroll.com/blog/data/2015/09/22/data-pipelines-docker.html ) +[Petabyte-Scale Data Pipelines with Docker, Luigi and Elastic Spot Instances]( https://tech.adroll.com/blog/data/2015/09/22/data-pipelines-docker.html ) -[Snowplow]( http://snowplowanalytics.com/product/ ) +[Snowplow]( https://snowplowanalytics.com/product/ ) diff --git a/docs/DevOps/Orchestrator_Scheduler/index.html b/docs/DevOps/Orchestrator_Scheduler/index.html deleted file mode 100644 index aa114d9..0000000 --- a/docs/DevOps/Orchestrator_Scheduler/index.html +++ /dev/null @@ -1,1990 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Orchestrators / Schedulers - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Java/Gradle.md b/docs/Java/Gradle.md similarity index 100% rename from docs_src/Java/Gradle.md rename to docs/Java/Gradle.md diff --git a/docs/Java/Gradle/index.html b/docs/Java/Gradle/index.html deleted file mode 100644 index cbd95cd..0000000 --- a/docs/Java/Gradle/index.html +++ /dev/null @@ -1,2246 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Gradle Basics - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Gradle

-

Install

-

In Windows 10 WSL, install sdkman

-
sudo apt install zip
-curl -s "https://get.sdkman.io" | bash
-source "$HOME/.sdkman/bin/sdkman-init.sh"
-sdk version
-
- -

Install gradle

-
sdk install gradle
-gradle -v
-
- -

Create a gradle project (for Java)

-
cd /mnt/d/code/gradle
-gradle init --type java-application  
-
- -

You can now use ./gradlew or gradlew.bat in the project folder

-

Usage with Java

-

Example for the JVM

-

Common commands

-
    -
  • ./gradlew tasks in your project directory lists which tasks you can run in your project, such as building or running your code.
  • -
  • ./gradlew projects
  • -
  • ./gradlew properties
  • -
-

Most commonly used Java tasks:

-
    -
  • ./gradlew build will compile your project's code into a /build folder.
  • -
  • ./gradlew run will run the compiled code in your build folder.
  • -
  • ./gradlew clean will purge that build folder.
  • -
  • ./gradlew test will execute unit tests without building or running your code again.
  • -
-

Build process

-
    -
  • Gradle launches as a new JVM process
  • -
  • It parses the gradle.properties file and configures Gradle accordingly
  • -
  • Next, it creates a Settings instance for the build
  • -
  • Then, it evaluates the settings.gradle file against the Settings object
  • -
  • It creates a hierarchy of Projects, based on the configured Settings object
  • -
  • Finally, it executes each build.gradle file against its project
  • -
-

In case of a multi-project build, we'd probably have multiple different build.gradle files, one for each project. -The build.gradle file is executed against a Project instance, with one Project instance created per subproject.

-

Groovy DSL

-

Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application.

-

Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.

-

Tasks

-

Tasks are snippets that we can run directly from the command line in our project directory via ./gradlew [TASK_NAME]

-
./gradlew copy
-
- -
task copy(type: Copy, group: "Custom", description: "Copies sources to the dest directory") {
-    from "src"
-    into "dest"
-}
-
-// accessing task properties
-println copy.destinationDir
-println project.copy.destinationDir
-
- -
task('copy2', type: Copy) {
-    description 'Copies the resource directory to the target directory.'
-    from(file('src'))
-    into(buildDir)
-    include('**/*.txt', '**/*.xml', '**/*.properties')
-    timeout = Duration.ofMillis(50000)
-}
-
- -
task hello {
-    group = 'Worthless tasks'
-    description = 'An utterly useless task'
-    // extra (custom) properties
-    ext.myProperty = "myValue"
-    doLast {
-        println 'Hello world!'
-    }
-}
-
-// API call
-hello.doLast {
-    println "Greetings from the $hello.name task."  // accessing task property in interpolated string
-}
-
-hello.configure {
-    doLast {
-        println 'Hello again'
-    }
-}
-
-task next {
-    dependsOn hello   // or 'hello' if lazy initialized - task dependency 
-    doLast {
-       println hello.myProperty
-    }
-}
-
- -
./gradlew -q hello
-./gradlew -q next
-
- -
// dynamic tasks
-4.times { counter ->
-    task "task$counter" {
-        doLast {
-            println "I'm task number $counter"
-        }
-    }
-}
-
-// default tasks
-defaultTasks 'task0', 'task1'
-
- -
import org.apache.commons.codec.binary.Base64
-
-// dependencies for the build script
-buildscript {
-    repositories {
-        mavenCentral()
-    }
-    dependencies {
-        classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
-    }
-}
-
-task encode {
-    doLast {
-        // using the build script dependencies
-        def byte[] encodedString = new Base64().encode('hello world\n'.getBytes())
-        println new String(encodedString)
-    }
-}
-
-// you can also declare methods
-File[] fileList(String dir) {
-    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
-}
-
- -

Plugins

-

https://plugins.gradle.org/

-
plugins {
-    id "base"
-}
-
- -

Essential plugins for Java:

-
plugins {
-    id 'java'
-    id 'application'
-}
-
-apply plugin:'application'
-
- -

Dependencies and repositories

-
repositories {
-    jcenter()  // or mavenCentral()
-}
-
-dependencies {
-    implementation 'com.google.guava:guava:26.0-jre'  // implementation is a configuration defined by the java plugin
-    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.13'
-
-    testImplementation 'junit:junit:4.12'
-}
-
-// pointer to the Java entrypoint
-mainClassName="com.someorg.someprj.App"
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/Java/Java.md b/docs/Java/Java.md new file mode 100644 index 0000000..5d5d872 --- /dev/null +++ b/docs/Java/Java.md @@ -0,0 +1,49 @@ +--- +title: Java Pointers +category: java +tags: libraries tools +comments: true +--- + +## Install [Java](https://www.java.com/en/) + +[JDK download](https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html) + +```bash +java -version +``` + +## Java Tools + +[List 1](https://www.loggly.com/blog/8-tools-for-every-java-developers-toolkit/) + +[List 2](https://blog.newrelic.com/2014/05/21/toolsforjavadevelopers/) + +- [Eclipse](https://eclipse.org/downloads/) IDE +- [Maven](https://maven.apache.org/download.cgi) or Graddle build tool +- [Nexus](https://www.sonatype.org/nexus/) private repository +- [Maven public repository](https://mvnrepository.com/) +- [Phabrikator](https://www.phacility.com/) code review + - [Phabrikator blog](https://scn.sap.com/community/abap/blog/2014/11/24/code-review-with-phabricator--an-open-source-software-engineering-platform) +- [Jenkins](https://jenkins.io/) CI / CD automation server +- [JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html) +- [FindBugs](https://findbugs.sourceforge.net/) static analysis or [Checker Framework](https://types.cs.washington.edu/checker-framework/) +- [Checkstyle](https://checkstyle.sourceforge.net/) coding standard checker + - [Style guidelines](https://logging.apache.org/log4j/2.x/javastyle.html) + +## Java Libraries + +[Libraries](https://www.devsaran.com/blog/16-java-development-tools-web-developers) + +- [Log4j](https://logging.apache.org/) +- [Spring](https://www.spring.io) + - [Spring Cloud for Amazon Web Services](https://cloud.spring.io/spring-cloud-aws/) + - [Spring boot code generator](https://start.spring.io/) +- [Apache Commons](https://commons.apache.org/) +- [Guava](https://github.com/google/guava) +- [Jackson JSON](https://wiki.fasterxml.com/JacksonHome) or [GSON](https://github.com/google/gson/blob/master/UserGuide.md) +- [Hibernate](https://hibernate.org/orm/) +on the JVM. +- [Play framework](https://www.playframework.com/) +- [Spark web microframework](https://sparkjava.com/) +- [Akka](https://akka.io/) - actor model, to build highly concurrent, distributed, and resilient message-driven applications diff --git a/docs/Java/Java/index.html b/docs/Java/Java/index.html deleted file mode 100644 index 205b75c..0000000 --- a/docs/Java/Java/index.html +++ /dev/null @@ -1,2025 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Java Pointers - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Java Pointers

- -

Install Java

-

JDK download

-
java -version
-
- -

Java Tools

-

List 1

-

List 2

- -

Java Libraries

-

Libraries

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Java/Log4j.md b/docs/Java/Log4j.md similarity index 74% rename from docs_src/Java/Log4j.md rename to docs/Java/Log4j.md index 70c98c0..2602fad 100644 --- a/docs_src/Java/Log4j.md +++ b/docs/Java/Log4j.md @@ -6,8 +6,7 @@ tags: Java Logs # Apache Log4j 2 -[Log4j quick guide]( http://www.tutorialspoint.com/log4j/log4j_quick_guide.htm ) - +[Log4j quick guide]( https://www.tutorialspoint.com/log4j/log4j_quick_guide.htm ) ## Key Components @@ -19,7 +18,7 @@ There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERRO ## Install -[Download Log4j]( +[Download Log4j]( https://logging.apache.org/log4j/2.x/download.html ) ```bash @@ -74,24 +73,24 @@ import org.apache.logging.log4j.Logger; public class MyTest { - private static final Logger logger = LogManager.getLogger(); // equiv to LogManager.getLogger(MyTest.class); - private static final Logger logger = LogManager.getLogger("HelloWorld"); + private static final Logger logger = LogManager.getLogger(); // equiv to LogManager.getLogger(MyTest.class); + private static final Logger logger = LogManager.getLogger("HelloWorld"); - public static void main(String[] args) { - logger.setLevel(Level.WARN); - logger.info("Hello, World!"); - // string interpolation - logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar()); + public static void main(String[] args) { + logger.setLevel(Level.WARN); + logger.info("Hello, World!"); + // string interpolation + logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar()); - // pre-Java 8 style optimization: explicitly check the log level - // to make sure the expensiveOperation() method is only called if necessary - if (logger.isTraceEnabled()) { - logger.trace("Some long-running operation returned {}", expensiveOperation()); - } + // pre-Java 8 style optimization: explicitly check the log level + // to make sure the expensiveOperation() method is only called if necessary + if (logger.isTraceEnabled()) { + logger.trace("Some long-running operation returned {}", expensiveOperation()); + } - // Java-8 style optimization: no need to explicitly check the log level: - // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace("Some long-running operation returned {}", () -> expensiveOperation()); - } + // Java-8 style optimization: no need to explicitly check the log level: + // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace("Some long-running operation returned {}", () -> expensiveOperation()); + } } // FORMATTER LOGGER diff --git a/docs/Java/Log4j/index.html b/docs/Java/Log4j/index.html deleted file mode 100644 index c8690ca..0000000 --- a/docs/Java/Log4j/index.html +++ /dev/null @@ -1,2111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Apache Log4j 2 - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Apache Log4j 2

-

Log4j quick guide

-

Key Components

-
    -
  • loggers: Responsible for capturing logging information.
  • -
  • appenders: Responsible for publishing logging information to various preferred destinations.
  • -
  • layouts: Responsible for formatting logging information in different styles.
  • -
-

There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERROR, WARN, FATAL, and ALL.

-

Install

-

Download Log4j

-
$ gunzip apache-log4j-1.2.15.tar.gz
-$ tar -xvf apache-log4j-1.2.15.tar
-$ pwd
-/usr/local/apache-log4j-1.2.15
-$ export CLASSPATH=$CLASSPATH:/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar
-$ export PATH=$PATH:/usr/local/apache-log4j-1.2.15/
-
- -

Maven Snippet

-
<dependencies>
-<dependency>
-<groupId>org.apache.logging.log4j</groupId>
-<artifactId>log4j-api</artifactId>
-<version>2.6.1</version>
-</dependency>
-<dependency>
-<groupId>org.apache.logging.log4j</groupId>
-<artifactId>log4j-core</artifactId>
-<version>2.6.1</version>
-</dependency>
-</dependencies>
-
- -

log4j.properties

-

All the libraries should be available in CLASSPATH and yourlog4j.properties file should be available in PATH.

-
# Define the root logger with appender file
-log = /usr/home/log4j
-log4j.rootLogger = WARN, FILE
-
-# Define the file appender
-log4j.appender.FILE=org.apache.log4j.FileAppender
-log4j.appender.FILE.File=${log}/log.out
-
-# Define the layout for file appender
-log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
-log4j.appender.FILE.layout.conversionPattern=%m%n
-
- -

Snippets

-
import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-public class MyTest {
-
-    private static final Logger logger = LogManager.getLogger(); // equiv to  LogManager.getLogger(MyTest.class);
-    private static final Logger logger = LogManager.getLogger("HelloWorld");
-
-    public static void main(String[] args) {
-         logger.setLevel(Level.WARN);
-         logger.info("Hello, World!");
-         // string interpolation
-         logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());
-
-         // pre-Java 8 style optimization: explicitly check the log level
-         // to make sure the expensiveOperation() method is only called if necessary
-         if (logger.isTraceEnabled()) {
-        logger.trace("Some long-running operation returned {}", expensiveOperation());
-         }
-
-         // Java-8 style optimization: no need to explicitly check the log level:
-         // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace("Some long-running operation returned {}", () -> expensiveOperation());
-         }
-}
-
-// FORMATTER LOGGER
-public static Logger logger = LogManager.getFormatterLogger("Foo");
-
-logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
-logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
-//
-logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Java/Maven.md b/docs/Java/Maven.md similarity index 89% rename from docs_src/Java/Maven.md rename to docs/Java/Maven.md index 39ec17a..9c46df8 100644 --- a/docs_src/Java/Maven.md +++ b/docs/Java/Maven.md @@ -1,6 +1,6 @@ ## Useful Links -[http://maven.apache.org/]( http://maven.apache.org/ ) +[https://maven.apache.org/]( https://maven.apache.org/ ) [Maven Cheatsheet]( https://eckobar.files.wordpress.com/2007/02/maven-cheatsheet.pdf ) @@ -8,9 +8,9 @@ [Apache-maven-2]( https://dzone.com/refcardz/apache-maven-2 ) -[Maven Basics]( http://deeplearning4j.org/maven.html ) +[Maven Basics]( https://deeplearning4j.org/maven.html ) -[Maven Download / Install]( http://maven.apache.org/download.cgi ) +[Maven Download / Install]( https://maven.apache.org/download.cgi ) [Nexus]( https://www.sonatype.com/nexus-repository-oss ) @@ -45,8 +45,8 @@ This directory contains your local Maven repository. When you download a depende [Introduction to the standard directory layout](https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html ) -Without customization, source code is assumed to be in ``${basedir}/src/main/java`` and resources are assumed to be in ``${basedir}/src/main/resources``. -Tests are assumed to be in ``${basedir}/src/test``, and a project is assumed to produce a JAR file. +Without customization, source code is assumed to be in ``${basedir}/src/main/java`` and resources are assumed to be in ``${basedir}/src/main/resources``. +Tests are assumed to be in ``${basedir}/src/test``, and a project is assumed to produce a JAR file. Maven assumes that you want the compile bytecode to ``${basedir}/target/classes`` and then create a distributable JAR file in ``${basedir}/target`` For [WAR files]( https://en.wikipedia.org/wiki/WAR_(file_format) ), the ``/WEB-INF`` directory contains a file named ``web.xml`` which defines the structure of the web application. @@ -131,7 +131,7 @@ You can run ``mvn site`` and then find an ``index.html`` file in ``target/site`` ## POM files -Use the search engine at [repository.sonatype.org]( http://repository.sonatype.org ) to find dependencies by name and get the ``xml`` necessary to paste into your ``pom.xml`` +Use the search engine at [repository.sonatype.org]( https://repository.sonatype.org ) to find dependencies by name and get the ``xml`` necessary to paste into your ``pom.xml`` ```xml diff --git a/docs/Java/Maven/index.html b/docs/Java/Maven/index.html deleted file mode 100644 index 5af7c38..0000000 --- a/docs/Java/Maven/index.html +++ /dev/null @@ -1,2145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Maven - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Maven

- - -

http://maven.apache.org/

-

Maven Cheatsheet

-

Maven Quick Ref

-

Apache-maven-2

-

Maven Basics

-

Maven Download / Install

-

Nexus

-

Basics

-
    -
  • Install:
  • -
-
cd /usr/local
-ln -s apache-maven-3.0.5 maven
-export PATH=/usr/local/maven/bin:$PATH
-mvn -v
-
- -
    -
  • Settings file:
  • -
-
~/.m2/settings.xml
-
- -

It contains user-specific configuration for authentication, repositories, and other information to customize the behavior of Maven.

-
    -
  • Maven Repo:
  • -
-
~/.m2/repository/
-
- -

This directory contains your local Maven repository. When you download a dependency from a remote Maven repository, Maven stores a copy of the dependency in your local repository.

-

Directory Layout

-

Introduction to the standard directory layout

-

Without customization, source code is assumed to be in ${basedir}/src/main/java and resources are assumed to be in ${basedir}/src/main/resources. -Tests are assumed to be in ${basedir}/src/test, and a project is assumed to produce a JAR file. -Maven assumes that you want the compile bytecode to ${basedir}/target/classes and then create a distributable JAR file in ${basedir}/target

-

For WAR files, the /WEB-INF directory contains a file named web.xml which defines the structure of the web application. -See also Tomcat Deployment guide

-

Cheatsheet

-
    -
  • Bring up a menu of choices
  • -
-
mvn archetype:generate -DgroupId=com.dw -DartifactId=es-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
-
- -
    -
  • Create a Java project
  • -
-
mvn archetype:create -DgroupId=org.yourcompany.project -DartifactId=application
-
- -
    -
  • Create a web project
  • -
-
mvn archetype:create -DgroupId=org.yourcompany.project -DartifactId=application -DarchetypeArtifactId=maven-archetype-webapp
-
- -
    -
  • Clean project (will delete target directory)
  • -
-
mvn clean
-
- -
    -
  • Validate project (validate the project is correct and all necessary information is available)
  • -
-
mvn validate
-
- -
    -
  • Compile project (compile source code, classes stored in target/classes)
  • -
-
mvn compile
-
- -
    -
  • Test project (run tests using a suitable unit testing framework)
  • -
-
mvn test
-
- -
    -
  • Package project (take the compiled code and package it in its distributable format, such as a JAR / WAR)
  • -
-
mvn package
-
- -
    -
  • Verify project (run any checks to verify the package is valid and meets quality criteria)
  • -
-
mvn verify
-
- -
    -
  • Install project (install the package into the local repository, for use as a dependency in other projects locally)
  • -
-
mvn install
-mvn clean install -DskipTests -Dmaven.javadoc.skip=true
-
- -
    -
  • Deploy project (done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects)
  • -
-
mvn deploy
-
- -
    -
  • Deploy-file (can be used for deploying a external jar file to repository)
  • -
-
mvn deploy:deploy-file -Dfile=/path/to/jar/file -DrepositoryId=repos-server -Durl=http ://repos.company.o
-
- -

You can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code.

-

POM files

-

Use the search engine at repository.sonatype.org to find dependencies by name and get the xml necessary to paste into your pom.xml

-
<project>
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.sonatype.mavenbook</groupId>
-  <artifactId>my-project</artifactId>
-  <version>1.0-SNAPSHOT</version>
-</project>
-
- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Java/Spring.md b/docs/Java/Spring.md similarity index 99% rename from docs_src/Java/Spring.md rename to docs/Java/Spring.md index e8607c7..5e99dc4 100644 --- a/docs_src/Java/Spring.md +++ b/docs/Java/Spring.md @@ -1,6 +1,5 @@ # Spring - All Spring beans are managed - they "live" inside a container, called "application context". Second, each application has an entry point to that context. Web applications have a Servlet, JSFuses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener. @@ -9,7 +8,6 @@ Autowiring happens by placing an instance of one bean into the desired field in What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there. - ## Spring and AWS [A New Way of Using Email for Support Apps: An AWS Tutorial]( diff --git a/docs/Java/Spring/index.html b/docs/Java/Spring/index.html deleted file mode 100644 index 01d020d..0000000 --- a/docs/Java/Spring/index.html +++ /dev/null @@ -1,1965 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Spring - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Spring

-

All Spring beans are managed - they "live" inside a container, called "application context".

-

Second, each application has an entry point to that context. Web applications have a Servlet, JSFuses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener.

-

Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.

-

What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there.

-

Spring and AWS

-

A New Way of Using Email for Support Apps: An AWS Tutorial

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Linux/Linux.md b/docs/Linux/Linux.md similarity index 76% rename from docs_src/Linux/Linux.md rename to docs/Linux/Linux.md index 814e499..586ea13 100644 --- a/docs_src/Linux/Linux.md +++ b/docs/Linux/Linux.md @@ -8,7 +8,7 @@ tags: [Vim Commands Cheat Sheet]( https://www.fprintf.net/vimCheatSheet.html ) -``` +```sh :q :q! :wq @@ -22,7 +22,7 @@ dd delete [count] lines ## Bash -- [BASH Programming - Introduction]( http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html ) +- [BASH Programming - Introduction]( https://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html ) - [Bash CheatSheet for UNIX Systems]( https://gist.github.com/LeCoupa/122b12050f5fb267e75f ) - [Bash Cheat Sheet]( ftp://ftp.psu.ac.th/pub/bash-howto/reference_bash-cheat.pdf ) @@ -35,10 +35,9 @@ echo $varname Don't forget chmod +x filename - ## Amazon Linux -[Amazon Linux Basics]( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonLinuxAMIBasics.html ) +[Amazon Linux Basics]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonLinuxAMIBasics.html ) ### Adding Packages @@ -58,8 +57,8 @@ sudo service nginx start ### Autostarting a service on Amazon Linux -- [Tutorial on "Chkconfig" Command in Linux with Examples]( http://www.yourownlinux.com/2015/01/tutorial-on-chkconfig-command-in-linux-with-examples.html ) -- [man page]( http://linux.die.net/man/8/chkconfig ) +- [Tutorial on "Chkconfig" Command in Linux with Examples]( https://www.yourownlinux.com/2015/01/tutorial-on-chkconfig-command-in-linux-with-examples.html ) +- [man page]( https://linux.die.net/man/8/chkconfig ) ```bash # check a service is configured for startup @@ -77,12 +76,11 @@ sudo chkconfig --level 3 httpd on # specific runlevel ## Linux Boot Process -- [ Linux Boot Process]( http://www.thegeekstuff.com/2011/02/linux-boot-process/ ) -- [ Scripts in /etc/init.d ]( http://www.novell.com/documentation/suse91/suselinux-adminguide/html/ch13s04.html ) +- [Linux Boot Process]( https://www.thegeekstuff.com/2011/02/linux-boot-process/ ) +- [Scripts in /etc/init.d]( https://www.novell.com/documentation/suse91/suselinux-adminguide/html/ch13s04.html ) You can also use a ``/etc/rc.d/rc.local`` script. - ### Running Commands on your Linux Instance at Launch - Paste a user data script into the ``User data`` field @@ -103,8 +101,8 @@ echo "" > /var/www/html/phpinfo.php ``` - Or use ``cloud-init`` - - [cloud-init for AWS EC2]( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonLinuxAMIBasics.html#CloudInit ) - - [cloud-init docs]( http://cloudinit.readthedocs.io/en/latest/ ) + - [cloud-init for AWS EC2]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonLinuxAMIBasics.html#CloudInit ) + - [cloud-init docs]( https://cloudinit.readthedocs.io/en/latest/ ) File location: ``/etc/sysconfig/cloudinit`` @@ -122,4 +120,3 @@ yum install -y amazon-ssm-agent.rpm ## Linux desktop [How can I connect to an Amazon EC2 Linux instance with desktop functionality from Windows?]( https://aws.amazon.com/premiumsupport/knowledge-center/connect-to-linux-desktop-from-windows/ ) - diff --git a/docs/Linux/Linux/index.html b/docs/Linux/Linux/index.html deleted file mode 100644 index 3bb7c7a..0000000 --- a/docs/Linux/Linux/index.html +++ /dev/null @@ -1,2206 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Linux Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Linux Cheatsheet

- -

Vim

-

Vim Commands Cheat Sheet

-
:q
-:q!
-:wq
-:wq {file}
-
-:e[dit] {file}
-
-i  insert
-dd  delete [count] lines
-
- -

Bash

- -
#!/bin/bash
-
-varname=value
-echo $varname
-
- -

Don't forget chmod +x filename

-

Amazon Linux

-

Amazon Linux Basics

-

Adding Packages

-
sudo yum update -y                  # all packages
-sudo yum install -y package_name
-sudo yum install -y httpd24 php56 mysql55-server php56-mysqlnd
-
- -

Start a Service

-
sudo service docker start
-sudo service jenkins start
-sudo service nginx start
-
- -

Autostarting a service on Amazon Linux

- -
# check a service is configured for startup
-sudo chkconfig sshd
-echo $?  # 0 = configured for startup
-# or
-sudo chkconfig --list mysqld
-sudo chkconfig --list         # all services
-
-# add a service
-sudo chkconfig --add vsftpd
-sudo chkconfig mysqld on
-sudo chkconfig --level 3 httpd on  # specific runlevel
-
- -

Linux Boot Process

- -

You can also use a /etc/rc.d/rc.local script.

-

Running Commands on your Linux Instance at Launch

-
    -
  • Paste a user data script into the User data field
  • -
-
#!/bin/bash
-yum update -y
-yum install -y httpd24 php56 mysql55-server php56-mysqlnd
-service httpd start
-chkconfig httpd on
-groupadd www
-usermod -a -G www ec2-user
-chown -R root:www /var/www
-chmod 2775 /var/www
-find /var/www -type d -exec chmod 2775 {} +
-find /var/www -type f -exec chmod 0664 {} +
-echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
-
- - -

File location: /etc/sysconfig/cloudinit

-

Cloud-init output log file: /var/log/cloud-init-output.log

-

Install the SSM Agent on EC2 Instances at Start-Up

-
#!/bin/bash
-cd /tmp
-curl https://amazon-ssm-region.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm
-yum install -y amazon-ssm-agent.rpm
-
- -

Linux desktop

-

How can I connect to an Amazon EC2 Linux instance with desktop functionality from Windows?

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/Linux/Virtualization.md b/docs/Linux/Virtualization.md new file mode 100644 index 0000000..4bf4323 --- /dev/null +++ b/docs/Linux/Virtualization.md @@ -0,0 +1,11 @@ +# Virtualization + +[Comparison of platform virtual machines]( https://en.wikipedia.org/wiki/Comparison_of_platform_virtual_machines ) + +[Linux KVM]( https://www.linux-kvm.org/ ) + +[Xen]( https://en.wikipedia.org/wiki/Xen ) + +[VMware ESX]( https://en.wikipedia.org/wiki/VMware_ESX ) + +[vSphere]( https://en.wikipedia.org/wiki/VSphere ) diff --git a/docs/Linux/Virtualization/index.html b/docs/Linux/Virtualization/index.html deleted file mode 100644 index f65effb..0000000 --- a/docs/Linux/Virtualization/index.html +++ /dev/null @@ -1,1920 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Virtualization - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Markup_and_Documentation/Jekyll.md b/docs/Markup_and_Documentation/Jekyll.md similarity index 80% rename from docs_src/Markup_and_Documentation/Jekyll.md rename to docs/Markup_and_Documentation/Jekyll.md index a81b04a..7997bda 100644 --- a/docs_src/Markup_and_Documentation/Jekyll.md +++ b/docs/Markup_and_Documentation/Jekyll.md @@ -8,7 +8,7 @@ tags: blog jekyll # Jekyll Basics -[Jekyll Home Page](http://jekyllrb.com) +[Jekyll Home Page](https://jekyllrb.com) Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk]. @@ -18,38 +18,37 @@ Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most ou [Jekyll source code](https://github.com/jekyll/jekyll) -[Guide to basic Jekyll](http://jmcglone.com/guides/github-pages/) +[Guide to basic Jekyll](https://jmcglone.com/guides/github-pages/) +## Jekyll Install How-To -# Jekyll Install How-To - -[Install Instructions](http://jekyllrb.com/docs/installation/) +[Install Instructions](https://jekyllrb.com/docs/installation/) - Install Ruby via [RubyInstaller](https://rubyinstaller.org/) - Update RubyGems ```bash -$ gem update --system +gem update --system ``` - Install Jekyll ```bash -$ gem install jekyll +gem install jekyll ``` - Test Jekyll ```bash -$ jekyll --version -$ gem list jekyll +jekyll --version +gem list jekyll ``` - Install bundler ```bash -$ gem install bundler +gem install bundler ``` [Bundler](https://rubygems.org/gems/bundler) is a gem that manages other Ruby gems. It makes sure your gems and gem versions are compatible, and that you have all necessary dependencies each gem requires. @@ -66,7 +65,7 @@ $ gem install bundler Jekyll installs a site that uses a gem-based theme called Minima. -With gem-based themes, some of the site’s directories (such as the assets, _layouts, _includes, and _sass directories) are stored in the theme’s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll’s build process. +With gem-based themes, some of the site’s directories (such as the assets, _layouts,_includes, and _sass directories) are stored in the theme’s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll’s build process. - Build site locally @@ -75,9 +74,9 @@ With gem-based themes, some of the site’s directories (such as the assets, _la ~/myblog $ bundle exec jekyll serve ``` -Now browse to [localhost:4000](http://localhost:4000) +Now browse to [localhost:4000](https://localhost:4000) -[Jekyll Quickstart](http://jekyllrb.com/docs/quickstart/) +[Jekyll Quickstart](https://jekyllrb.com/docs/quickstart/) When you run bundle exec jekyll serve, Bundler uses the gems and versions as specified in Gemfile.lock to ensure your Jekyll site builds with no compatibility or dependency conflicts. @@ -88,11 +87,11 @@ $ jekyll build # => The current folder will be generated into ./_site $ jekyll serve -# => A development server will run at http://localhost:4000/ +# => A development server will run at https://localhost:4000/ # Auto-regeneration: enabled. Use `--no-watch` to disable. ``` -# Plugins +## Plugins ```bash $ gem install jekyll-sitemap @@ -112,7 +111,7 @@ gems: # Custom Search -[Adding a custom Google search](http://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/) +[Adding a custom Google search](https://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/) # Themes @@ -122,7 +121,8 @@ gems: To change theme, search for jekyll theme on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes. Add the theme to your site’s Gemfile: -``` + +```bash gem "jekyll-theme-tactile" ``` @@ -135,24 +135,21 @@ $ bundle show jekyll-theme-tactile Add the following to your site’s _config.yml to activate the theme: -``` +```yaml theme: jekyll-theme-tactile ``` Build your site: ```bash -$ bundle exec jekyll serve +bundle exec jekyll serve ``` - - You can find out info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/) You can find the source code for the Jekyll minima theme at: [minima](https://github.com/jekyll/minima) - --------------------------------------------------- You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. @@ -161,15 +158,12 @@ To add new posts, simply add a file in the `_posts` directory that follows the c Jekyll also offers powerful support for code snippets: +```md {% highlight ruby %} def print_hi(name) puts "Hi, #{name}" end print_hi('Tom') -#=> prints 'Hi, Tom' to STDOUT. +# => prints 'Hi, Tom' to STDOUT. {% endhighlight %} - - - - - +``` diff --git a/docs/Markup_and_Documentation/Jekyll/index.html b/docs/Markup_and_Documentation/Jekyll/index.html deleted file mode 100644 index 76527f8..0000000 --- a/docs/Markup_and_Documentation/Jekyll/index.html +++ /dev/null @@ -1,2043 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Jekyll How-To - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Jekyll Basics

-

Jekyll Home Page

-

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk.

-

Jekyll source code

-

Guide to basic Jekyll

-

Jekyll Install How-To

-

Install Instructions

- -
$ gem update --system
-
- -
    -
  • Install Jekyll
  • -
-
$ gem install jekyll
-
- -
    -
  • Test Jekyll
  • -
-
$ jekyll --version
-$ gem list jekyll
-
- -
    -
  • Install bundler
  • -
-
$ gem install bundler
-
- -

Bundler is a gem that manages other Ruby gems. It makes sure your gems and gem versions are compatible, and that you have all necessary dependencies each gem requires.

-
    -
  • Create a new site
  • -
-
# Create a new Jekyll site at ./myblog
-~ $ jekyll new myblog
-
-# Change into your new directory
-~ $ cd myblog
-
- -

Jekyll installs a site that uses a gem-based theme called Minima.

-

With gem-based themes, some of the site’s directories (such as the assets, _layouts, _includes, and _sass directories) are stored in the theme’s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll’s build process.

-
    -
  • Build site locally
  • -
-
# Build the site on the preview server
-~/myblog $ bundle exec jekyll serve
-
- -

Now browse to localhost:4000

-

Jekyll Quickstart

-

When you run bundle exec jekyll serve, Bundler uses the gems and versions as specified in Gemfile.lock to ensure your Jekyll site builds with no compatibility or dependency conflicts.

-

The Gemfile and Gemfile.lock files inform Bundler about the gem requirements in your site. If your site doesn’t have these Gemfiles, you can omit bundle exec and just run jekyll serve.

-
$ jekyll build
-# => The current folder will be generated into ./_site
-
-$ jekyll serve
-# => A development server will run at http://localhost:4000/
-# Auto-regeneration: enabled. Use `--no-watch` to disable.
-
- -

Plugins

-
$ gem install jekyll-sitemap
-$ gem install jekyll-feed
-etc...
-
- -

Add to _config.yml

-
gems:
-  - jekyll-paginate
-  - jekyll-feed
-  - jekyll-sitemap
-``
-
-
-# Custom Search
-
-[Adding a custom Google search](http://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/)
-
-
-# Themes
-
-[Theme documentation](https://jekyllrb.com/docs/themes/)
-
-To change theme, search for jekyll theme on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes.
-
-Add the theme to your site’s Gemfile:
-
- -

gem "jekyll-theme-tactile"

-
```bash
-$ bundle install
-
-# check proper install
-$ bundle show jekyll-theme-tactile
-
- -

Add the following to your site’s _config.yml to activate the theme:

-
theme: jekyll-theme-tactile
-
- -

Build your site:

-
$ bundle exec jekyll serve
-
- -

You can find out info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at jekyllrb.com

-

You can find the source code for the Jekyll minima theme at: -minima

-
-

You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.

-

To add new posts, simply add a file in the _posts directory that follows the convention YYYY-MM-DD-name-of-post.ext and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works.

-

Jekyll also offers powerful support for code snippets:

-

{% highlight ruby %} -def print_hi(name) - puts "Hi, #{name}" -end -print_hi('Tom')

-

=> prints 'Hi, Tom' to STDOUT.

-

{% endhighlight %}

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Markup_and_Documentation/Markdown.md b/docs/Markup_and_Documentation/Markdown.md similarity index 56% rename from docs_src/Markup_and_Documentation/Markdown.md rename to docs/Markup_and_Documentation/Markdown.md index 6870310..851613f 100644 --- a/docs_src/Markup_and_Documentation/Markdown.md +++ b/docs/Markup_and_Documentation/Markdown.md @@ -6,18 +6,17 @@ tags: github # Markdown Essentials -[Markdown main site](http://daringfireball.net/projects/markdown/) +[Markdown main site](https://daringfireball.net/projects/markdown/) [GitHub Flavored Markdown Guide](https://guides.github.com/features/mastering-markdown/) - ## Basics -A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs. +A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs. Do not indent normal paragraphs with spaces or tabs. Indent at least 4 spaces or a tab for code blocks. -```markdown +```txt Syntax highlighted code block # Header 1 @@ -37,89 +36,94 @@ Syntax highlighted code block ## Emphasis - *single asterisks* - _single underscores_ - **double asterisks** - __double underscores__ - - Emphasis can be used in the mi\*dd\*le of a word. - +```txt + *single asterisks* + _single underscores_ + **double asterisks** + __double underscores__ +``` +Emphasis can be used in the `mi\*dd\*le of a word`. ## Headers - # H1 - ## H2 - ### H3 - #### H4 - ##### H5 - ###### H6 +```txt + # H1 + ## H2 + ### H3 + #### H4 + ##### H5 + ###### H6 - Alt-H1 - ====== + Alt-H1 + ====== - Alt-H2 - ------ + Alt-H2 + ------ +``` -## Links and Images +## Links and Images - [ Text for the link ](URL) +```txt + [Text for the link](URL) - This is [an example][id] reference-style link. - [id]: http://example.com/ "Optional Title Here" - - ![Alt text](/path/to/img.jpg "Optional title") + This is [an example][id] reference-style link. + [id]: https://example.com/ "Optional Title Here" -## Code + ![Alt text](/path/to/img.jpg "Optional title") +``` - `span of code` +## Code + `span of code` - ```python +~~~txt +```python - def wiki_rocks(text): - formatter = lambda t: "funky"+t - return formatter(text) - ``` + def wiki_rocks(text): + formatter = lambda t: "funky"+t + return formatter(text) +``` +~~~ will be displayed as ```python def wiki_rocks(text): - formatter = lambda t: "funky"+t - return formatter(text) + formatter = lambda t: "funky"+t + return formatter(text) ``` ## Blockquotes - > This is a blockquote with two paragraphs. - > - > Second paragraph. - +```txt + > This is a blockquote with two paragraphs. + > + > Second paragraph. +``` ## GitHub Pages -[GitHub Pages documentation](https://help.github.com/categories/github-pages-basics/) +[GitHub Pages documentation](https://help.github.com/categories/github-pages-basics/) GitHub Pages site will use the layout and styles from the Jekyll theme you have selected in your [repository settings](https://github.com/john-cd/john-cd.github.io/settings). The name of this theme is saved in the Jekyll `_config.yml` configuration file. +## Bitbucket +Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. +[Safe mode](https://pythonhosted.org/Markdown/reference.html#safe_mode) requires that you replace, remove, or escape HTML tags appropriately. -## Bitbucket +Code highlighting to bitbucket README.md written in Python Markdown -Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. -[Safe mode](http://pythonhosted.org/Markdown/reference.html#safe_mode) requires that you replace, remove, or escape HTML tags appropriately. - -Code highlighting to bitbucket README.md written in Python Markdown - - :::python + :::python friends = ['john', 'pat', 'gary', 'michael'] for i, name in enumerate(friends): print "iteration {iteration} is {name}".format(iteration=i, name=name) -[Python markdown main site](http://pythonhosted.org//Markdown/) - +[Python markdown main site](https://pythonhosted.org//Markdown/) #### [Cloning your Bitbucket Wiki](https://confluence.atlassian.com/display/BITBUCKET/View+and+edit+pages) - $ git clone http://bitbucket.org/MY_USER/MY_REPO/wiki \ No newline at end of file +```bash +git clone https://bitbucket.org/MY_USER/MY_REPO/wiki +``` diff --git a/docs/Markup_and_Documentation/Markdown/index.html b/docs/Markup_and_Documentation/Markdown/index.html deleted file mode 100644 index e502ce0..0000000 --- a/docs/Markup_and_Documentation/Markdown/index.html +++ /dev/null @@ -1,2180 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Markdown Essentials - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Markdown Essentials

-

Markdown main site

-

GitHub Flavored Markdown Guide

-

Basics

-

A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs.

-

Do not indent normal paragraphs with spaces or tabs. Indent at least 4 spaces or a tab for code blocks.

-
Syntax highlighted code block
-
-# Header 1
-## Header 2
-### Header 3
-
-- Bulleted
-- List
-
-1. Numbered
-2. List
-
-**Bold** and _Italic_ and `Code` text
-
-[Link](url) and ![Image](src)
-
- -

Emphasis

-
*single asterisks*
-_single underscores_
-**double asterisks**
-__double underscores__
-
-Emphasis can be used in the mi\*dd\*le of a word.
-
- -

Headers

-
# H1
-## H2
-### H3
-#### H4
-##### H5
-###### H6
-
-Alt-H1
-======
-
-Alt-H2
-------
-
- - -
[ Text for the link ](URL)
-
-This is [an example][id] reference-style link.
-[id]: http://example.com/  "Optional Title Here"
-
-![Alt text](/path/to/img.jpg "Optional title")
-
- -

Code

-
`span of code`
-
-
-```python
-
-def wiki_rocks(text):
-    formatter = lambda t: "funky"+t
-    return formatter(text)
-```
-
- -

will be displayed as

-
def wiki_rocks(text):
-    formatter = lambda t: "funky"+t
-    return formatter(text)
-
- -

Blockquotes

-
> This is a blockquote with two paragraphs. 
-> 
-> Second paragraph.
-
- -

GitHub Pages

-

GitHub Pages documentation

-

GitHub Pages site will use the layout and styles from the Jekyll theme you have selected in your repository settings. The name of this theme is saved in the Jekyll _config.yml configuration file.

-

Bitbucket

-

Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. -Safe mode requires that you replace, remove, or escape HTML tags appropriately.

-

Code highlighting to bitbucket README.md written in Python Markdown

-
    friends = ['john', 'pat', 'gary', 'michael']
-    for i, name in enumerate(friends):
-        print "iteration {iteration} is {name}".format(iteration=i, name=name)
-
- -

Python markdown main site

-

Cloning your Bitbucket Wiki

-
$ git clone http://bitbucket.org/MY_USER/MY_REPO/wiki
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Markup_and_Documentation/MkDocs.md b/docs/Markup_and_Documentation/MkDocs.md similarity index 65% rename from docs_src/Markup_and_Documentation/MkDocs.md rename to docs/Markup_and_Documentation/MkDocs.md index c1171d0..bdebaad 100644 --- a/docs_src/Markup_and_Documentation/MkDocs.md +++ b/docs/Markup_and_Documentation/MkDocs.md @@ -1,11 +1,10 @@ --- title: MkDocs Basics category: markup -tags: python +tags: python --- -This website is generated by [mkdocs.org]( http://mkdocs.org ) and the [Material Theme]( http://squidfunk.github.io/mkdocs-material/ ). - +This website is generated by [mkdocs.org]( https://mkdocs.org ) and the [Material Theme]( https://squidfunk.github.io/mkdocs-material/ ). ## Basic MkDocs Commands @@ -14,36 +13,41 @@ This website is generated by [mkdocs.org]( http://mkdocs.org ) and the [Material * `mkdocs build` - Build the documentation site. * `mkdocs help` - Print this help message. - ## Install and documentation generation -[mkdocs.org](http://mkdocs.org). +[mkdocs.org](https://mkdocs.org). To install MkDocs / create a new documentation site: + ```bash -$ pip install mkdocs -$ mkdocs new documentation +pip install mkdocs +mkdocs new documentation ``` To build the documentation site: + ```bash -$ cd documentation -$ mkdocs build +cd documentation +mkdocs build ``` -To start the live-reloading docs server - [http://localhost:8000/](http://localhost:8000/) +To start the live-reloading docs server - [https://localhost:8000/](https://localhost:8000/) + ```bash -$ mkdocs serve +mkdocs serve ``` MkDocs can use the ghp-import tool to commit to the gh-pages branch and push the gh-pages branch to GitHub Pages: + ```bash -$ mkdocs gh-deploy +mkdocs gh-deploy ``` ### MkDocs project layout +```txt mkdocs.yml # The configuration file. docs/ index.md # The documentation homepage. ... # Other markdown pages, images and other files. +``` diff --git a/docs/Markup_and_Documentation/MkDocs/index.html b/docs/Markup_and_Documentation/MkDocs/index.html deleted file mode 100644 index dd21dce..0000000 --- a/docs/Markup_and_Documentation/MkDocs/index.html +++ /dev/null @@ -1,2030 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - MkDocs Basics - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

MkDocs Basics

- -

This website is generated by mkdocs.org and the Material Theme.

-

Basic MkDocs Commands

-
    -
  • mkdocs new [dir-name] - Create a new project.
  • -
  • mkdocs serve - Start the live-reloading docs server.
  • -
  • mkdocs build - Build the documentation site.
  • -
  • mkdocs help - Print this help message.
  • -
-

Install and documentation generation

-

mkdocs.org.

-

To install MkDocs / create a new documentation site:

-
$ pip install mkdocs
-$ mkdocs new documentation
-
- -

To build the documentation site:

-
$ cd documentation
-$ mkdocs build
-
- -

To start the live-reloading docs server - http://localhost:8000/

-
$ mkdocs serve
-
- -

MkDocs can use the ghp-import tool to commit to the gh-pages branch and push the gh-pages branch to GitHub Pages:

-
$ mkdocs gh-deploy
-
- -

MkDocs project layout

-
mkdocs.yml    # The configuration file.
-docs/
-    index.md  # The documentation homepage.
-    ...       # Other markdown pages, images and other files.
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/Markup_and_Documentation/reStructuredText.md b/docs/Markup_and_Documentation/reStructuredText.md new file mode 100644 index 0000000..b7542eb --- /dev/null +++ b/docs/Markup_and_Documentation/reStructuredText.md @@ -0,0 +1,347 @@ +--- +title: reStructuredText Cheatsheet +category: markup +tags: python +--- + +# [reStructuredText](https://docutils.sourceforge.net/rst.html) + +[reStructuredText Quick Ref](https://docutils.sourceforge.net/docs/user/rst/quickref.html) + +[reStructuredText Cheat Sheet](https://docutils.sourceforge.net/docs/user/rst/cheatsheet.txt) (see below) + +## reST Short Overview + +All reST files use an indentation of 3 spaces; no tabs are allowed. +The maximum line length is 80 characters for normal text, but tables, +deeply indented code samples and long links may extend beyond that. +Code example bodies should use normal Python 4-space indentation. +Paragraphs are simply chunks of text separated by one or more blank lines. +As in Python, indentation is significant in reST, so all lines of the same +paragraph must be left-aligned to the same level of indentation. + +Section headers are created by underlining (and optionally overlining) +the section title with a punctuation character, at least as long as the text: + +```txt + ================= + This is a heading + ================= + # with overline, for parts + * with overline, for chapters + = for sections + - for subsections + ^ for subsubsections + " for paragraphs + + one asterisk: *text* for emphasis (italics), + two asterisks: **text** for strong emphasis (boldface), and + backquotes: ``text`` for code samples. + escape with a backslash \ + + * This is a bulleted list. + * It has two items, the second + item uses two lines. + + 1. This is a numbered list. + 2. It has two items too. + + . This is a numbered list. + . It has two items too. +``` + +Nested lists are possible, but be aware that they must be separated from the +parent list items by blank lines + +## Source Code Double Colon + +```txt +This is a normal text paragraph. The next paragraph is a code sample:: + + It is not processed in any way, except + that the indentation is removed. + + It can span multiple lines. + +This is a normal text paragraph again. +``` + +## Links + + `Link text `_ for inline web links. + +## Definitions + +```txt + term (up to a line of text) + Definition of the term, which must be indented and + can even consist of multiple paragraphs + + next term + Description. +``` + +### Footnotes + +```txt + Lorem ipsum [#]_ dolor sit amet ... [#]_ +``` + +## Use of reStructuredText in Python docstrings + +See + +```py + # Typical function documentation: + + :param volume_id: The ID of the EBS volume to be attached. + :type volume_id: str + + :param instance_id: The ID of the EC2 instance + :type instance_id: str + + :return: `Reverse geocoder return value`_ dictionary giving closest + address(es) to `(lat, lng)` + :rtype: dict + :raises GoogleMapsError: If the coordinates could not be reverse geocoded. + + Keyword arguments and return value are identical to those of :meth:`geocode()`. + + .. _`Reverse geocoder return value`: + https://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding +``` + +- Normal docstring formatting conventions apply: see PEP 257. +- Identifier references go in \`backticks\`. +- `:param lat: some text` _documents parameters_ +- `:type lat: float` _documents parameter types_ +- `:return:` dictionary giving some info... _documents return values_ +- `:rtype: dict` _documents return type_ +- `:raises SomeError:` sometext... _documents exceptions raised_ +- `>>>` _starts a doctest and is automatically formatted as code_ +- Code can also be indicated by indenting four spaces or preceding with `::` and a blank line +- Link to other methods, functions, classes, modules with :meth:`mymethod`, +- :func:`myfunc`, :class:`myclass`, and :mod:`mymodule`. +- Hyperlink names go in backticks with a trailing underscore: `Google`_ +- Targets can be defined anywhere with: `.. _Google: https://www.google.com/` + +## Explicit Markup + +An explicit markup block begins with a line starting with .. followed by +whitespace and is terminated by the next paragraph at the same level of +indentation. (There needs to be a blank line between explicit markup +and normal paragraphs. + +```txt + .. sectionauthor:: Guido van Rossum + + .. rubric:: Footnotes + + .. [#] Text of the first footnote. + .. [#] Text of the second footnote. + + + :mod:`parrot` -- Dead parrot access + =================================== + + .. module:: parrot + :platform: Unix, Windows + :synopsis: Analyze and reanimate dead parrots. + .. moduleauthor:: Eric Cleese + .. moduleauthor:: John Idle + + .. function:: repeat([repeat=3[, number=1000000]]) + repeat(y, z) + :bar: no + + Return a line of text input from the user. + + + .. class:: Spam + + Description of the class. + + .. data:: ham + + Description of the attribute. +``` + +## Inline markup + +```txt + :rolename:`content` or :role:`title ` + + :meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text. +``` + +The following roles refer to objects in modules and are possibly hyperlinked +if a matching identifier is found: + +**mod** + +The name of a module; a dotted name may be used. This should also be used for package names. + +**func** + +The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers. + +**data** + +The name of a module-level variable or constant. + +**const** + +The name of a “defined” constant. This may be a C-language #define or a Python variable that is not intended to be changed. + +**class** + +A class name; a dotted name may be used. + +**meth** + +The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used. + +**attr** + +The name of a data attribute of an object. + +**exc** + +The name of an exception. A dotted name may be used. + +# Official reStructuredText Cheatsheet + +```txt + ===================================================== + The reStructuredText_ Cheat Sheet: Syntax Reminders + ===================================================== + :Info: See for introductory docs. + :Author: David Goodger + :Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $ + :Revision: $Revision: 7612 $ + :Description: This is a "docinfo block", or bibliographic field list + + .. NOTE:: If you are reading this as HTML, please read + ``_ instead to see the input syntax examples! + + Section Structure + ================= + Section titles are underlined or overlined & underlined. + + Body Elements + ============= + Grid table: + + +--------------------------------+-----------------------------------+ + | Paragraphs are flush-left, | Literal block, preceded by "::":: | + | separated by blank lines. | | + | | Indented | + | Block quotes are indented. | | + +--------------------------------+ or:: | + | >>> print 'Doctest block' | | + | Doctest block | > Quoted | + +--------------------------------+-----------------------------------+ + | | Line blocks preserve line breaks & indents. [new in 0.3.6] | + | | Useful for addresses, verse, and adornment-free lists; long | + | lines can be wrapped with continuation lines. | + +--------------------------------------------------------------------+ + + Simple tables: + + ================ ============================================================ + List Type Examples (syntax in the `text source `_) + ================ ============================================================ + Bullet list * items begin with "-", "+", or "*" + Enumerated list 1. items use any variation of "1.", "A)", and "(i)" + #. also auto-enumerated + Definition list Term is flush-left : optional classifier + Definition is indented, no blank line between + Field list :field name: field body + Option list -o at least 2 spaces between option & description + ================ ============================================================ + + ================ ============================================================ + Explicit Markup Examples (visible in the `text source`_) + ================ ============================================================ + Footnote .. [1] Manually numbered or [#] auto-numbered + (even [#labelled]) or [*] auto-symbol + Citation .. [CIT2002] A citation. + Hyperlink Target .. _reStructuredText: https://docutils.sf.net/rst.html + .. _indirect target: reStructuredText_ + .. _internal target: + Anonymous Target __ https://docutils.sf.net/docs/ref/rst/restructuredtext.html + Directive ("::") .. image:: images/biohazard.png + Substitution Def .. |substitution| replace:: like an inline directive + Comment .. is anything else + Empty Comment (".." on a line by itself, with blank lines before & after, + used to separate indentation contexts) + ================ ============================================================ + + Inline Markup + ============= + *emphasis*; **strong emphasis**; `interpreted text`; `interpreted text + with role`:emphasis:; ``inline literal text``; standalone hyperlink, + https://docutils.sourceforge.net; named reference, reStructuredText_; + `anonymous reference`__; footnote reference, [1]_; citation reference, + [CIT2002]_; |substitution|; _`inline internal target`. + + Directive Quick Reference + ========================= + See for full info. + + ================ ============================================================ + Directive Name Description (Docutils version added to, in [brackets]) + ================ ============================================================ + attention Specific admonition; also "caution", "danger", + "error", "hint", "important", "note", "tip", "warning" + admonition Generic titled admonition: ``.. admonition:: By The Way`` + image ``.. image:: picture.png``; many options possible + figure Like "image", but with optional caption and legend + topic ``.. topic:: Title``; like a mini section + sidebar ``.. sidebar:: Title``; like a mini parallel document + parsed-literal A literal block with parsed inline markup + rubric ``.. rubric:: Informal Heading`` + epigraph Block quote with class="epigraph" + highlights Block quote with class="highlights" + pull-quote Block quote with class="pull-quote" + compound Compound paragraphs [0.3.6] + container Generic block-level container element [0.3.10] + table Create a titled table [0.3.1] + list-table Create a table from a uniform two-level bullet list [0.3.8] + csv-table Create a table from CSV data [0.3.4] + contents Generate a table of contents + sectnum Automatically number sections, subsections, etc. + header, footer Create document decorations [0.3.8] + target-notes Create an explicit footnote for each external target + math Mathematical notation (input in LaTeX format) + meta HTML-specific metadata + include Read an external reST file as if it were inline + raw Non-reST data passed untouched to the Writer + replace Replacement text for substitution definitions + unicode Unicode character code conversion for substitution defs + date Generates today's date; for substitution defs + class Set a "class" attribute on the next element + role Create a custom interpreted text role [0.3.2] + default-role Set the default interpreted text role [0.3.10] + title Set the metadata document title [0.3.10] + ================ ============================================================ + + Interpreted Text Role Quick Reference + ===================================== + See for full info. + + ================ ============================================================ + Role Name Description + ================ ============================================================ + emphasis Equivalent to *emphasis* + literal Equivalent to ``literal`` but processes backslash escapes + math Mathematical notation (input in LaTeX format) + PEP Reference to a numbered Python Enhancement Proposal + RFC Reference to a numbered Internet Request For Comments + raw For non-reST data; cannot be used directly (see docs) [0.3.6] + strong Equivalent to **strong** + sub Subscript + sup Superscript + title Title reference (book, etc.); standard default role + ================ ============================================================ +``` diff --git a/docs/Markup_and_Documentation/reStructuredText/index.html b/docs/Markup_and_Documentation/reStructuredText/index.html deleted file mode 100644 index db55ce5..0000000 --- a/docs/Markup_and_Documentation/reStructuredText/index.html +++ /dev/null @@ -1,2371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - reStructuredText Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

reStructuredText

-

reStructuredText Quick Ref

-

reStructuredText Cheat Sheet (see below)

-

reST Short Overview

-

All reST files use an indentation of 3 spaces; no tabs are allowed. -The maximum line length is 80 characters for normal text, but tables, -deeply indented code samples and long links may extend beyond that. -Code example bodies should use normal Python 4-space indentation. -Paragraphs are simply chunks of text separated by one or more blank lines. -As in Python, indentation is significant in reST, so all lines of the same -paragraph must be left-aligned to the same level of indentation.

-

Section headers are created by underlining (and optionally overlining) -the section title with a punctuation character, at least as long as the text:

-
=================
-This is a heading
-=================
-# with overline, for parts
-* with overline, for chapters
-= for sections
-- for subsections
-^ for subsubsections
-" for paragraphs
-
-one asterisk: *text* for emphasis (italics),
-two asterisks: **text** for strong emphasis (boldface), and
-backquotes: ``text`` for code samples.
-escape with a backslash \
-
-* This is a bulleted list.
-* It has two items, the second
-  item uses two lines.
-
-1. This is a numbered list.
-2. It has two items too.
-
-. This is a numbered list.
-. It has two items too.
-
- -

Nested lists are possible, but be aware that they must be separated from the -parent list items by blank lines

-

Source Code Double Colon

-
This is a normal text paragraph. The next paragraph is a code sample::
-
-       It is not processed in any way, except
-       that the indentation is removed.
-
-       It can span multiple lines.
-
-This is a normal text paragraph again.
-
- - -
`Link text <http://target>`_ for inline web links.
-
- -

Definitions

-
term (up to a line of text)
-   Definition of the term, which must be indented and 
-   can even consist of multiple paragraphs
-
-next term
-   Description.
-
- -

Footnotes

-
Lorem ipsum [#]_ dolor sit amet ... [#]_
-
- -

Use of reStructuredText in Python docstrings

-

See http://infinitemonkeycorps.net/docs/pph/

-
    # Typical function documentation: 
-
-    :param volume_id: The ID of the EBS volume to be attached.
-    :type volume_id: str
-
-    :param instance_id: The ID of the EC2 instance 
-    :type instance_id: str
-
-    :return: `Reverse geocoder return value`_ dictionary giving closest
-        address(es) to `(lat, lng)`
-    :rtype: dict
-    :raises GoogleMapsError: If the coordinates could not be reverse geocoded.
-
-    Keyword arguments and return value are identical to those of :meth:`geocode()`.
-
-    .. _`Reverse geocoder return value`:
-        http://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding
-
- -
    -
  • Normal docstring formatting conventions apply: see PEP 257.
  • -
  • Identifier references go in `backticks`.
  • -
  • :param lat: some text documents parameters
  • -
  • :type lat: float documents parameter types
  • -
  • :return: dictionary giving some info... documents return values
  • -
  • :rtype: dict documents return type
  • -
  • :raises SomeError: sometext... documents exceptions raised
  • -
  • >>> starts a doctest and is automatically formatted as code
  • -
  • Code can also be indicated by indenting four spaces or preceding with :: and a blank line
  • -
  • Link to other methods, functions, classes, modules with :meth:mymethod,
  • -
  • :func:myfunc, :class:myclass, and :mod:mymodule.
  • -
  • Hyperlink names go in backticks with a trailing underscore: Google_
  • -
  • Targets can be defined anywhere with: .. _Google: http://www.google.com/
  • -
-

Explicit Markup

-

An explicit markup block begins with a line starting with .. followed by -whitespace and is terminated by the next paragraph at the same level of -indentation. (There needs to be a blank line between explicit markup -and normal paragraphs.

-
.. sectionauthor:: Guido van Rossum <guido@python.org>
-
-.. rubric:: Footnotes
-
-.. [#] Text of the first footnote.
-.. [#] Text of the second footnote.
-
-
-:mod:`parrot` -- Dead parrot access
-===================================
-
-.. module:: parrot
-   :platform: Unix, Windows
-   :synopsis: Analyze and reanimate dead parrots.
-.. moduleauthor:: Eric Cleese <eric@python.invalid>
-.. moduleauthor:: John Idle <john@python.invalid>
-
-.. function:: repeat([repeat=3[, number=1000000]])
-              repeat(y, z)
-   :bar: no
-
-   Return a line of text input from the user.
-
-
-.. class:: Spam
-
-      Description of the class.
-
-      .. data:: ham
-
-         Description of the attribute.
-
- -

Inline markup

-
:rolename:`content`  or  :role:`title <target>`
-
-:meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text.
-
- -

The following roles refer to objects in modules and are possibly hyperlinked -if a matching identifier is found:

-

mod

-

The name of a module; a dotted name may be used. This should also be used for package names.

-

func

-

The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers.

-

data

-

The name of a module-level variable or constant.

-

const

-

The name of a “defined” constant. This may be a C-language #define or a Python variable that is not intended to be changed.

-

class

-

A class name; a dotted name may be used.

-

meth

-

The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used.

-

attr

-

The name of a data attribute of an object.

-

exc

-

The name of an exception. A dotted name may be used.

-

Official reStructuredText Cheatsheet

-
=====================================================
- The reStructuredText_ Cheat Sheet: Syntax Reminders
-=====================================================
-:Info: See <http://docutils.sf.net/rst.html> for introductory docs.
-:Author: David Goodger <goodger@python.org>
-:Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $
-:Revision: $Revision: 7612 $
-:Description: This is a "docinfo block", or bibliographic field list
-
-.. NOTE:: If you are reading this as HTML, please read
-   `<cheatsheet.txt>`_ instead to see the input syntax examples!
-
-Section Structure
-=================
-Section titles are underlined or overlined & underlined.
-
-Body Elements
-=============
-Grid table:
-
-+--------------------------------+-----------------------------------+
-| Paragraphs are flush-left,     | Literal block, preceded by "::":: |
-| separated by blank lines.      |                                   |
-|                                |     Indented                      |
-|     Block quotes are indented. |                                   |
-+--------------------------------+ or::                              |
-| >>> print 'Doctest block'      |                                   |
-| Doctest block                  | > Quoted                          |
-+--------------------------------+-----------------------------------+
-| | Line blocks preserve line breaks & indents. [new in 0.3.6]       |
-| |     Useful for addresses, verse, and adornment-free lists; long  |
-|       lines can be wrapped with continuation lines.                |
-+--------------------------------------------------------------------+
-
-Simple tables:
-
-================  ============================================================
-List Type         Examples (syntax in the `text source <cheatsheet.txt>`_)
-================  ============================================================
-Bullet list       * items begin with "-", "+", or "*"
-Enumerated list   1. items use any variation of "1.", "A)", and "(i)"
-                  #. also auto-enumerated
-Definition list   Term is flush-left : optional classifier
-                      Definition is indented, no blank line between
-Field list        :field name: field body
-Option list       -o  at least 2 spaces between option & description
-================  ============================================================
-
-================  ============================================================
-Explicit Markup   Examples (visible in the `text source`_)
-================  ============================================================
-Footnote          .. [1] Manually numbered or [#] auto-numbered
-                     (even [#labelled]) or [*] auto-symbol
-Citation          .. [CIT2002] A citation.
-Hyperlink Target  .. _reStructuredText: http://docutils.sf.net/rst.html
-                  .. _indirect target: reStructuredText_
-                  .. _internal target:
-Anonymous Target  __ http://docutils.sf.net/docs/ref/rst/restructuredtext.html
-Directive ("::")  .. image:: images/biohazard.png
-Substitution Def  .. |substitution| replace:: like an inline directive
-Comment           .. is anything else
-Empty Comment     (".." on a line by itself, with blank lines before & after,
-                  used to separate indentation contexts)
-================  ============================================================
-
-Inline Markup
-=============
-*emphasis*; **strong emphasis**; `interpreted text`; `interpreted text
-with role`:emphasis:; ``inline literal text``; standalone hyperlink,
-http://docutils.sourceforge.net; named reference, reStructuredText_;
-`anonymous reference`__; footnote reference, [1]_; citation reference,
-[CIT2002]_; |substitution|; _`inline internal target`.
-
-Directive Quick Reference
-=========================
-See <http://docutils.sf.net/docs/ref/rst/directives.html> for full info.
-
-================  ============================================================
-Directive Name    Description (Docutils version added to, in [brackets])
-================  ============================================================
-attention         Specific admonition; also "caution", "danger",
-                  "error", "hint", "important", "note", "tip", "warning"
-admonition        Generic titled admonition: ``.. admonition:: By The Way``
-image             ``.. image:: picture.png``; many options possible
-figure            Like "image", but with optional caption and legend
-topic             ``.. topic:: Title``; like a mini section
-sidebar           ``.. sidebar:: Title``; like a mini parallel document
-parsed-literal    A literal block with parsed inline markup
-rubric            ``.. rubric:: Informal Heading``
-epigraph          Block quote with class="epigraph"
-highlights        Block quote with class="highlights"
-pull-quote        Block quote with class="pull-quote"
-compound          Compound paragraphs [0.3.6]
-container         Generic block-level container element [0.3.10]
-table             Create a titled table [0.3.1]
-list-table        Create a table from a uniform two-level bullet list [0.3.8]
-csv-table         Create a table from CSV data [0.3.4]
-contents          Generate a table of contents
-sectnum           Automatically number sections, subsections, etc.
-header, footer    Create document decorations [0.3.8]
-target-notes      Create an explicit footnote for each external target
-math              Mathematical notation (input in LaTeX format)
-meta              HTML-specific metadata
-include           Read an external reST file as if it were inline
-raw               Non-reST data passed untouched to the Writer
-replace           Replacement text for substitution definitions
-unicode           Unicode character code conversion for substitution defs
-date              Generates today's date; for substitution defs
-class             Set a "class" attribute on the next element
-role              Create a custom interpreted text role [0.3.2]
-default-role      Set the default interpreted text role [0.3.10]
-title             Set the metadata document title [0.3.10]
-================  ============================================================
-
-Interpreted Text Role Quick Reference
-=====================================
-See <http://docutils.sf.net/docs/ref/rst/roles.html> for full info.
-
-================  ============================================================
-Role Name         Description
-================  ============================================================
-emphasis          Equivalent to *emphasis*
-literal           Equivalent to ``literal`` but processes backslash escapes
-math              Mathematical notation (input in LaTeX format)
-PEP               Reference to a numbered Python Enhancement Proposal
-RFC               Reference to a numbered Internet Request For Comments
-raw               For non-reST data; cannot be used directly (see docs) [0.3.6]
-strong            Equivalent to **strong**
-sub               Subscript
-sup               Superscript
-title             Title reference (book, etc.); standard default role
-================  ============================================================
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Microservices/Microservices.md b/docs/Microservices/Microservices.md similarity index 51% rename from docs_src/Microservices/Microservices.md rename to docs/Microservices/Microservices.md index fd25019..2490457 100644 --- a/docs_src/Microservices/Microservices.md +++ b/docs/Microservices/Microservices.md @@ -6,15 +6,14 @@ tags: microservices ## MicroServices -[ microservices.io ]( http://microservices.io/patterns/index.html ) +[microservices.io]( https://microservices.io/patterns/index.html ) -[ Introduction to microservices ](https://www.nginx.com/blog/introduction-to-microservices/) +[Introduction to microservices](https://www.nginx.com/blog/introduction-to-microservices/) ### Scala -[Lagom]( https://www.lagomframework.com/ ) +[Lagom]( https://www.lagomframework.com/ ) ### .NET [Microservices in C#]( https://docs.microsoft.com/en-us/dotnet/articles/csharp/tutorials/microservices ) - diff --git a/docs/Microservices/Microservices/index.html b/docs/Microservices/Microservices/index.html deleted file mode 100644 index 98cc6ba..0000000 --- a/docs/Microservices/Microservices/index.html +++ /dev/null @@ -1,2003 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Microservices - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Privacy/Privacy_engineering.md b/docs/Privacy/Privacy_engineering.md similarity index 100% rename from docs_src/Privacy/Privacy_engineering.md rename to docs/Privacy/Privacy_engineering.md diff --git a/docs/Privacy/Privacy_engineering/index.html b/docs/Privacy/Privacy_engineering/index.html deleted file mode 100644 index faa12e4..0000000 --- a/docs/Privacy/Privacy_engineering/index.html +++ /dev/null @@ -1,1963 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Privacy Engineering - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Python/Flask.md b/docs/Python/Flask.md similarity index 72% rename from docs_src/Python/Flask.md rename to docs/Python/Flask.md index ff254e8..375e57a 100644 --- a/docs_src/Python/Flask.md +++ b/docs/Python/Flask.md @@ -14,4 +14,4 @@ tags: web [Flask-RESTPlus]( https://flask-restplus.readthedocs.io/en/stable/ ) -[Building beautiful REST APIs using Flask, Swagger UI and Flask-RESTPlus]( http://michal.karzynski.pl/blog/2016/06/19/building-beautiful-restful-apis-using-flask-swagger-ui-flask-restplus/ ) +[Building beautiful REST APIs using Flask, Swagger UI and Flask-RESTPlus]( https://michal.karzynski.pl/blog/2016/06/19/building-beautiful-restful-apis-using-flask-swagger-ui-flask-restplus/ ) diff --git a/docs/Python/Flask/index.html b/docs/Python/Flask/index.html deleted file mode 100644 index a6d195a..0000000 --- a/docs/Python/Flask/index.html +++ /dev/null @@ -1,1966 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Flask - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - - -
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Python/Jupyter.md b/docs/Python/Jupyter.md similarity index 85% rename from docs_src/Python/Jupyter.md rename to docs/Python/Jupyter.md index 973d79a..16850e4 100644 --- a/docs_src/Python/Jupyter.md +++ b/docs/Python/Jupyter.md @@ -3,13 +3,13 @@ title: IPython / Jupyter Cheatsheet category: python tags: --- -### [IPython]( http://ipython.org/ ) / [Jupyter]( http://jupyter.org/ ) +### [IPython]( https://ipython.org/ ) / [Jupyter]( https://jupyter.org/ ) - Using IPython makes interactive work easy. - - Better shell - - Notebook interface - - Embeddable kernel - - Parallel python + - Better shell + - Notebook interface + - Embeddable kernel + - Parallel python ### IPython shell shortcuts @@ -17,7 +17,7 @@ tags: - ~ and * directory / file expansion - many "magic" methods: -``` +```py %lsmagic # list of all magic methods %quickref # cheatsheet %magic @@ -25,7 +25,7 @@ tags: ### Help -``` +```txt ? # overall help help # python help system ?someobj or someobj? # help @@ -38,23 +38,23 @@ help # python help system To run a program directly from the IPython console: -``` +```py %run somescript.py # instead of execfile("somescript.py") at the python prompt ``` ``%run`` has special flags for timing the execution of your scripts (``-t``) or for running them under the control of either Python's pdb debugger (``-d``) or profiler (``-p``): -``` +```py %run -d myscript.py ``` ### Other Commands -``` +```py %edit %ed # edit then execute %save %load example.py # load local (example) file (or url) allowing modification -%load http://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py +%load https://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py %macro # define macro with range of history lines, filenames or string objects %recall @@ -68,7 +68,7 @@ To run a program directly from the IPython console: ### Debugging -``` +```py %debug # jump into the Python debugger (pdb) %pdb # start the debugger on any uncaught exception. @@ -79,7 +79,7 @@ To run a program directly from the IPython console: ### OS Commands -``` +```txt !OScommand !ping www.bbc.co.uk %alias # system command alias @@ -87,7 +87,7 @@ To run a program directly from the IPython console: ### History -``` +```py _ __ ___ # etc... for previous outputs. _i _ii _i4 # etc.. for previous input. _ih for list of previous inputs ``` @@ -96,7 +96,7 @@ _i _ii _i4 # etc.. for previous input. _ih for list of previous inp Start with ``ipython --gui=qt`` or at the IPython prompt: -``` +```py %gui wx ``` @@ -108,7 +108,7 @@ Start with: ``ipython --matplotlib`` ( or ``--matplotlib=qt`` etc...) At the IPython prompt: -``` +```py %matplotlib # set matplotlib to work interactively; does not import anythig %matplotlib inline %matplotlib qt # request a specific GUI backend @@ -129,25 +129,25 @@ from pylab import * from numpy import * ``` -### [Qtconsole - an improved console]( http://ipython.org/ipython-doc/stable/interactive/qtconsole.html ) +### [Qtconsole - an improved console]( https://ipython.org/ipython-doc/stable/interactive/qtconsole.html ) At the command prompt: -``` +```py ipython.exe qtconsole --pylab=inline --ConsoleWidget.font_size=10 ``` alternative: --matplotlib inline or within IPython: -``` +```py %matplotlib inline %pylab inline ``` To embed plots, SVG or HTML in qtconsole, call display: -``` +```py from IPython.core.display import display, display_html from IPython.core.display import display_png, display_svg display(plt.gcf()) # embeds the current figure in the qtconsole @@ -158,18 +158,19 @@ plt.plot(np.rand(100)) display(f) ``` -[ipython and ipython notebook for matlab users]( http://xcorr.net/2013/04/19/ipython-and-ipython-notebook-for-matlab-users/ ) +[ipython and ipython notebook for matlab users]( https://xcorr.net/2013/04/19/ipython-and-ipython-notebook-for-matlab-users/ ) ### IPython Notebook web-based interface - Start with: ipython notebook and switch to browser - Keyboard shortcuts: - - ``Enter`` to edit a cell - - ``Shift + Enter`` to evaluate - - ``Ctrl + m`` or ``Esc`` for the "command mode" + - ``Enter`` to edit a cell + - ``Shift + Enter`` to evaluate + - ``Ctrl + m`` or ``Esc`` for the "command mode" In command mode: +```txt h list of keyboard shortcuts 1-6 to convert to heading cell m to convert to markdown cell @@ -178,13 +179,12 @@ In command mode: d d delete cell s save notebook . to restart kernel +``` -# Papermill +## Papermill [Papermill]( https://papermill.readthedocs.io/en/latest/ ) Papermill is a tool for parameterizing and executing Jupyter Notebooks. [Papermill GitHub]( https://github.com/nteract/papermill ) - - diff --git a/docs/Python/Jupyter/index.html b/docs/Python/Jupyter/index.html deleted file mode 100644 index 1356c2e..0000000 --- a/docs/Python/Jupyter/index.html +++ /dev/null @@ -1,2066 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - IPython / Jupyter Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

IPython / Jupyter

-
    -
  • Using IPython makes interactive work easy.
      -
    • Better shell
    • -
    • Notebook interface
    • -
    • Embeddable kernel
    • -
    • Parallel python
    • -
    -
  • -
-

IPython shell shortcuts

-
    -
  • TAB expansion to complete python names and file paths
  • -
  • ~ and * directory / file expansion
  • -
  • many "magic" methods:
  • -
-
%lsmagic                # list of all magic methods
-%quickref               # cheatsheet
-%magic
-
- -

Help

-
?                       # overall help
-help                    # python help system
-?someobj or someobj?    # help
-??someobj or someobj??  # detailed help
-
- -

%pdoc %pdef %psource for docstring, function definition, source code only.

-

Run

-

To run a program directly from the IPython console:

-
%run somescript.py      # instead of execfile("somescript.py") at the python prompt
-
- -

%run has special flags for timing the execution of your scripts (-t) or for running them under the control of either Python's pdb debugger (-d) or profiler (-p):

-
%run -d myscript.py
-
- -

Other Commands

-
%edit %ed               # edit then execute
-%save
-%load example.py        # load local (example) file (or url) allowing modification
-%load http://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py
-%macro                  # define macro with range of history lines, filenames or string objects
-%recall
-
-%whos                   # list identifiers you have defined interactively
-%reset  -f -s           # remove objects -f for force -s for soft (leaves history).
-
- -
    -
  • %reset is not a kernel restart
  • -
  • Restart with Ctrl+. in "qtconsole"
  • -
  • import module ; reload(module) to reload a module from disk
  • -
-

Debugging

-
%debug                  # jump into the Python debugger (pdb)
-%pdb                    # start the debugger on any uncaught exception.
-
-%cd                     # change directory
-%pwd                    # print working directory
-%env                    # OS environment variables
-
- -

OS Commands

-
!OScommand
-!ping www.bbc.co.uk
-%alias                  # system command alias
-
- -

History

-
_ __ ___                # etc... for previous outputs.
-_i _ii _i4              # etc.. for previous input. _ih for list of previous inputs
-
- -

GUI integration

-

Start with ipython --gui=qt or at the IPython prompt:

-
%gui wx
-
- -

Arguments can be wx, qt, gtk and tk.

-

Matplotlib / pylab graphics in an iPython shell

-

Start with: ipython --matplotlib ( or --matplotlib=qt etc...)

-

At the IPython prompt:

-
%matplotlib             # set matplotlib to work interactively; does not import anythig
-%matplotlib  inline
-%matplotlib qt          # request a specific GUI backend
-%pylab inline
-
- -

%pylab makes the following imports:

-
import numpy
-import matplotlib
-from matplotlib import pylab, mlab, pyplot
-np = numpy
-plt = pyplot
-from IPython.display import display
-from IPython.core.pylabtools import figsize, getfigs
-from pylab import *
-from numpy import *
-
- -

Qtconsole - an improved console

-

At the command prompt:

-
ipython.exe qtconsole --pylab=inline --ConsoleWidget.font_size=10
-
- -

alternative: --matplotlib inline -or within IPython:

-
%matplotlib  inline
-%pylab inline
-
- -

To embed plots, SVG or HTML in qtconsole, call display:

-
from IPython.core.display import display, display_html
-from IPython.core.display import display_png, display_svg
-display(plt.gcf()) # embeds the current figure in the qtconsole
-display(*getfigs()) # embeds all active figures in the qtconsole
-#or:
-f = plt.figure()
-plt.plot(np.rand(100))
-display(f)
-
- -

ipython and ipython notebook for matlab users

-

IPython Notebook web-based interface

-
    -
  • Start with: ipython notebook and switch to browser
  • -
  • Keyboard shortcuts:
      -
    • Enter to edit a cell
    • -
    • Shift + Enter to evaluate
    • -
    • Ctrl + m or Esc for the "command mode"
    • -
    -
  • -
-

In command mode:

-
 h list of keyboard shortcuts
- 1-6 to convert to heading cell
- m to convert to markdown cell
- y to convert to code
- c copy / v paste
- d d delete cell
- s save notebook
- . to restart kernel
-
- -

Papermill

-

Papermill

-

Papermill is a tool for parameterizing and executing Jupyter Notebooks.

-

Papermill GitHub

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Python/Matplotlib.md b/docs/Python/Matplotlib.md similarity index 70% rename from docs_src/Python/Matplotlib.md rename to docs/Python/Matplotlib.md index 4f5c97a..49f510e 100644 --- a/docs_src/Python/Matplotlib.md +++ b/docs/Python/Matplotlib.md @@ -6,24 +6,24 @@ tags: data visualization # Matplotlib Cheatsheet -Matplotlib prepares 2D (and some 3D) graphics. - -- Main page: http://www.matplotlib.org -- Image gallery: http://matplotlib.org/gallery.html -- pyplot command summary: http://matplotlib.org/api/pyplot_summary.html -- Examples http://matplotlib.org/examples/index.html -- Tutorial: http://www.loria.fr/~rougier/teaching/matplotlib/ -- See also: https://www.wakari.io/nb/url///wakari.io/static/notebooks/Lecture_4_Matplotlib.ipynb +Matplotlib prepares 2D (and some 3D) graphics. + +- Main page: +- Image gallery: +- pyplot command summary: +- Examples +- Tutorial: +- See also: ## Matplotlib, pylab, and pyplot: how are they related? - Matplotlib is the whole package. Pylab and matplotlib.pyplot (pyplot in the following) are modules in matplotlib. -- Pyplot makes matplotlib work like MATLAB. -- Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module). -- Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc.... +- Pyplot makes matplotlib work like MATLAB. +- Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module). +- Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc.... - Pyplot is __stateful__, in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes. -- Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like. -- The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting). +- Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like. +- The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting). - The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing. ## Examples diff --git a/docs/Python/Matplotlib/index.html b/docs/Python/Matplotlib/index.html deleted file mode 100644 index df35b93..0000000 --- a/docs/Python/Matplotlib/index.html +++ /dev/null @@ -1,2020 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Matplotlib Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Matplotlib Cheatsheet

-

Matplotlib prepares 2D (and some 3D) graphics.

-
    -
  • Main page: http://www.matplotlib.org
  • -
  • Image gallery: http://matplotlib.org/gallery.html
  • -
  • pyplot command summary: http://matplotlib.org/api/pyplot_summary.html
  • -
  • Examples http://matplotlib.org/examples/index.html
  • -
  • Tutorial: http://www.loria.fr/~rougier/teaching/matplotlib/
  • -
  • See also: https://www.wakari.io/nb/url///wakari.io/static/notebooks/Lecture_4_Matplotlib.ipynb
  • -
- -
    -
  • Matplotlib is the whole package. Pylab and matplotlib.pyplot (pyplot in the following) are modules in matplotlib.
  • -
  • Pyplot makes matplotlib work like MATLAB.
  • -
  • Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module).
  • -
  • Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc....
  • -
  • Pyplot is stateful, in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes.
  • -
  • Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like.
  • -
  • The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting).
  • -
  • The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing.
  • -
-

Examples

-
import numpy as np
-import matplotlib.pyplot as plt
-
-# Compute the x and y coordinates for points on sine and cosine curves
-x = np.arange(0, 3 * np.pi, 0.1)
-y_sin = np.sin(x)
-y_cos = np.cos(x)
-
-# Set up a subplot grid that has height 2 and width 1,
-# and set the first such subplot as active.
-plt.subplot(2, 1, 1)
-
-# Make the first plot
-plt.plot(x, y_sin)
-plt.title('Sine')
-
-# Set the second subplot as active, and make the second plot.
-plt.subplot(2, 1, 2)
-plt.plot(x, y_cos)
-plt.title('Cosine')
-
-# Show the figure.
-plt.show()
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Python/Python.md b/docs/Python/Python.md similarity index 96% rename from docs_src/Python/Python.md rename to docs/Python/Python.md index ec18df5..38106a6 100644 --- a/docs_src/Python/Python.md +++ b/docs/Python/Python.md @@ -1,11 +1,10 @@ --- title: Python Links category: python -tags: +tags: --- -# Python useful links - +# Python useful links ## Python environments @@ -17,7 +16,7 @@ python3 -m venv /path/to/new/virtual/environment [Virtualenv]( https://virtualenv.pypa.io/en/stable/ ) -virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.). +virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.). [pip-tools]( https://github.com/jazzband/pip-tools ) @@ -36,7 +35,6 @@ The problems that Pipenv seeks to solve are multi-faceted: [Pyenv]( https://realpython.com/intro-to-pyenv/ ) for managing multiple Python versions - ## Testing [Mockito]( https://mockito-python.readthedocs.io/en/latest/) @@ -57,7 +55,7 @@ Twine is a utility for publishing Python packages on PyPI. ## Build tools -[Buildout, an automation tool written in and extended with Python]( http://www.buildout.org/en/latest/ ) +[Buildout, an automation tool written in and extended with Python]( https://www.buildout.org/en/latest/ ) [PyBuilder]( https://pybuilder.github.io/ ) diff --git a/docs/Python/Python/index.html b/docs/Python/Python/index.html deleted file mode 100644 index c842283..0000000 --- a/docs/Python/Python/index.html +++ /dev/null @@ -1,2053 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Python Links - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Python useful links

-

Python environments

-

venv — Creation of virtual environments

-
python3 -m venv /path/to/new/virtual/environment
-
- -

Virtualenv

-

virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.).

-

pip-tools

-

A set of command line tools to help you keep your pip-based packages fresh, even when you've pinned them.

-

Pipenv

-

The problems that Pipenv seeks to solve are multi-faceted:

-
    -
  • You no longer need to use pip and virtualenv separately. They work together.
  • -
  • Managing a requirements.txt file can be problematic, so Pipenv uses Pipfile and Pipfile.lock to separate abstract dependency declarations from the last tested combination.
  • -
  • Hashes are used everywhere, always. Security. Automatically expose security vulnerabilities.
  • -
  • Strongly encourage the use of the latest versions of dependencies to minimize security risks arising from outdated components.
  • -
  • Give you insight into your dependency graph (e.g. $ pipenv graph).
  • -
  • Streamline development workflow by loading .env files.
  • -
-

Pyenv for managing multiple Python versions

-

Testing

-

Mockito

-

Code coverage measurement for Python

-

mechanize - Automate interaction with HTTP web servers

-

Packaging

-

Cookiecutter template for a Python package

-

Python Packaging User Guide

-

Twine

-

Twine is a utility for publishing Python packages on PyPI.

-

Build tools

-

Buildout, an automation tool written in and extended with Python

-

PyBuilder

-

Uranium: a Python Build System

-

Other

-

Python Anywhere

-

Host, run, and code Python in the cloud

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Python/Python3.md b/docs/Python/Python3.md similarity index 90% rename from docs_src/Python/Python3.md rename to docs/Python/Python3.md index debe4f7..0238e94 100644 --- a/docs_src/Python/Python3.md +++ b/docs/Python/Python3.md @@ -1,14 +1,13 @@ --- title: Python 3 category: python -tags: +tags: --- ## What's new in Python 3.x [What's really new in Python 3](https://powerfulpython.com/blog/whats-really-new-in-python-3/) - ### nonlocal / global ```python @@ -48,7 +47,7 @@ print("global:", x) # global: 2 ``` -### String interpolation - new in 3.6 +### String interpolation - new in 3.6 ```python name="David" @@ -57,7 +56,7 @@ value = decimal.Decimal("10.4507") print(f"result: {value:10.5}" ) # width precision ``` -### PEP 492 - Coroutines with async and await syntax +### PEP 492 - Coroutines with async and await syntax [async and await](https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/) @@ -124,12 +123,11 @@ else: - dict comprehension: ``{i: i ** 2 async for i in agen()}`` - generator expression: ``(i ** 2 async for i in agen())`` - ### Type hinting [PEP 484](https://www.python.org/dev/peps/pep-0484/) -[mypy-lang.org](http://mypy-lang.org/index.html) +[mypy-lang.org](https://mypy-lang.org/index.html) ```python def greet(name: str) -> str @@ -144,13 +142,14 @@ def retry(url: Url, retry_count: int) -> None: ... ``` ```python -from typing import TypeVar, Iterable, Tuple +from typing import TypeVar, Iterable, Tuple ``` -Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int] + +Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int] ```python -T = TypeVar('T', int, float, complex) # T is either or an int, a float or a complex -Vector = Iterable[Tuple[T, T]] # +T = TypeVar('T', int, float, complex) # T is either or an int, a float or a complex +Vector = Iterable[Tuple[T, T]] # def inproduct(v: Vector[T]) -> T: return sum(x*y for x, y in v) @@ -171,4 +170,4 @@ Callable[[Arg1Type, Arg2Type], ReturnType] ```python x = [] # type: List[Employee] x, y, z = [], [], [] # type: List[int], List[int], List[str] -``` \ No newline at end of file +``` diff --git a/docs/Python/Python3/index.html b/docs/Python/Python3/index.html deleted file mode 100644 index 0a07cb7..0000000 --- a/docs/Python/Python3/index.html +++ /dev/null @@ -1,2255 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Python 3 - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
- -
-
- - -
-
- - - - - - - -

Python 3

- -

What's new in Python 3.x

-

What's really new in Python 3

-

nonlocal / global

-
x = 0
-def outer():
-  x = 1
-  def inner():
-  nonlocal x
-  x = 2
-  print("inner:", x)
-
-  inner()
-  print("outer:", x)
-
-outer()
-print("global:", x)
-
-# inner: 2
-# outer: 2
-# global: 0
-
-## with global
-x = 0
-def outer():
-     x = 1
-     def inner():
-           global x
-           x = 2
-           print("inner:", x)
-  inner()
-  print("outer:", x)
-outer()
-print("global:", x)
-
-# inner: 2
-# outer: 1
-# global: 2
-
- -

String interpolation - new in 3.6

-
name="David"
-f"My name is {name}"
-value = decimal.Decimal("10.4507")
-print(f"result: {value:10.5}" )  # width precision
-
- -

PEP 492 - Coroutines with async and await syntax

-

async and await

-

yield from iterator

-

is equivalent

-
for x in iterator:
-     yield x
-
- -

Example:

-
def lazy_range(up_to):
-     """Generator to return the sequence of integers from 0 to up_to, exclusive."""
-     index = 0
-     def gratuitous_refactor():
-           nonlocal index
-           while index < up_to:
-               yield index
-               index += 1
-     yield from gratuitous_refactor()
-
- -

New 3.6 syntax:

-
async def func(param1, param2):
-    do_stuff()
-    await some_coroutine()
-
-async def read_data(db):
-  data = await db.fetch('SELECT ...')
-
-async def display_date(loop):
-  end_time = loop.time() + 5.0
-  while True:
-  print(datetime.datetime.now())
-  if (loop.time() + 1.0) >= end_time:
-  break
-  await asyncio.sleep(1)
-
-
-loop = asyncio.get_event_loop()# Blocking call which returns when the display_date() coroutine is done
-loop.run_until_complete(display_date(loop))
-loop.close()
-
- -

Async for

-
async for TARGET in ITER:
-  BLOCK
-else:
-  BLOCK2
-
- -

Async improvements - 3.6

-
    -
  • set comprehension: {i async for i in agen()}
  • -
  • list comprehension: [i async for i in agen()]
  • -
  • dict comprehension: {i: i ** 2 async for i in agen()}
  • -
  • generator expression: (i ** 2 async for i in agen())
  • -
-

Type hinting

-

PEP 484

-

mypy-lang.org

-
def greet(name: str) -> str
-    return 'Hello there, {}'.format(name)
-
- -

Type aliases

-
Url = str
-def retry(url: Url, retry_count: int) -> None: ...
-
- -
from typing import TypeVar, Iterable, Tuple   
-
- -

Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int]

-
T = TypeVar('T', int, float, complex)  # T is either or an int, a float or a complex 
-Vector = Iterable[Tuple[T, T]]          # 
-
-def inproduct(v: Vector[T]) -> T:
-       return sum(x*y for x, y in v)
-
-def dilate(v: Vector[T], scale: T) -> Vector[T]:
-       return ((x * scale, y * scale) for x, y in v)
-vec = [] # type: Vector[float]
-
- -

For functions

-
Callable[[Arg1Type, Arg2Type], ReturnType]
-
- -

Type comments

-
x = []   # type: List[Employee]
-x, y, z = [], [], []  # type: List[int], List[int], List[str]
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Akka.md b/docs/Scala/Akka.md similarity index 99% rename from docs_src/Scala/Akka.md rename to docs/Scala/Akka.md index 19c35f2..8cae194 100644 --- a/docs_src/Scala/Akka.md +++ b/docs/Scala/Akka.md @@ -1,7 +1,7 @@ --- title: Akka Cheatsheet category: Scala -tags: +tags: --- # Akka @@ -128,7 +128,3 @@ object AkkaQuickstart extends App { //#main-class //#full-example ``` - - - - diff --git a/docs/Scala/Akka/index.html b/docs/Scala/Akka/index.html deleted file mode 100644 index a627ba4..0000000 --- a/docs/Scala/Akka/index.html +++ /dev/null @@ -1,2079 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Akka Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Akka

-

Actors have:

-
    -
  • A mailbox (the queue where messages end up).
  • -
  • A behavior (the state of the actor, internal variables etc.).
  • -
  • Messages (pieces of data representing a signal, similar to method calls and their parameters).
  • -
  • An execution environment (the machinery that takes actors that have messages to react to and invokes their message handling code).
  • -
  • An address.
  • -
-

sbt:

-
libraryDependencies ++= Seq(
-  "com.typesafe.akka" %% "akka-actor" % "2.5.6",
-  "com.typesafe.akka" %% "akka-testkit" % "2.5.6" % Test
-)
-
- -

Basic Example

-
//#full-example
-package com.lightbend.akka.sample
-
-import akka.actor.{ Actor, ActorLogging, ActorRef, ActorSystem, Props }
-import scala.io.StdIn
-
-//#greeter-companion
-//#greeter-messages
-object Greeter {
-  //#greeter-messages
-  def props(message: String, printerActor: ActorRef): Props = Props(new Greeter(message, printerActor))
-  //#greeter-messages
-  final case class WhoToGreet(who: String)
-  case object Greet
-}
-//#greeter-messages
-//#greeter-companion
-
-//#greeter-actor
-class Greeter(message: String, printerActor: ActorRef) extends Actor {
-  import Greeter._
-  import Printer._
-
-  var greeting = ""
-
-  def receive = {
-    case WhoToGreet(who) =>
-      greeting = s"$message, $who"
-    case Greet           =>
-      //#greeter-send-message
-      printerActor ! Greeting(greeting)
-      //#greeter-send-message
-  }
-}
-//#greeter-actor
-
-//#printer-companion
-//#printer-messages
-object Printer {
-  //#printer-messages
-  def props: Props = Props[Printer]
-  //#printer-messages
-  final case class Greeting(greeting: String)
-}
-//#printer-messages
-//#printer-companion
-
-//#printer-actor
-class Printer extends Actor with ActorLogging {
-  import Printer._
-
-  def receive = {
-    case Greeting(greeting) =>
-      log.info(s"Greeting received (from ${sender()}): $greeting")
-  }
-}
-//#printer-actor
-
-//#main-class
-object AkkaQuickstart extends App {
-  import Greeter._
-
-  // Create the 'helloAkka' actor system
-  val system: ActorSystem = ActorSystem("helloAkka")
-
-  try {
-    //#create-actors
-    // Create the printer actor
-    val printer: ActorRef = system.actorOf(Printer.props, "printerActor")
-
-    // Create the 'greeter' actors
-    val howdyGreeter: ActorRef =
-      system.actorOf(Greeter.props("Howdy", printer), "howdyGreeter")
-    val helloGreeter: ActorRef =
-      system.actorOf(Greeter.props("Hello", printer), "helloGreeter")
-    val goodDayGreeter: ActorRef =
-      system.actorOf(Greeter.props("Good day", printer), "goodDayGreeter")
-    //#create-actors
-
-    //#main-send-messages
-    howdyGreeter ! WhoToGreet("Akka")
-    howdyGreeter ! Greet
-
-    howdyGreeter ! WhoToGreet("Lightbend")
-    howdyGreeter ! Greet
-
-    helloGreeter ! WhoToGreet("Scala")
-    helloGreeter ! Greet
-
-    goodDayGreeter ! WhoToGreet("Play")
-    goodDayGreeter ! Greet
-    //#main-send-messages
-
-    println(">>> Press ENTER to exit <<<")
-    StdIn.readLine()
-  } finally {
-    system.terminate()
-  }
-}
-//#main-class
-//#full-example
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Play_Framework.md b/docs/Scala/Play_Framework.md similarity index 98% rename from docs_src/Scala/Play_Framework.md rename to docs/Scala/Play_Framework.md index 166368d..6e2f746 100644 --- a/docs_src/Scala/Play_Framework.md +++ b/docs/Scala/Play_Framework.md @@ -1,19 +1,18 @@ --- title: Play Framework category: Scala -tag: Scala Akka Play Web REST +tag: Scala Akka Play Web REST --- ## Links [Play Framework](https://playframework.com/documentation/) - ## The Play application layout The layout of a Play application is standardized to keep things as simple as possible. After a first successful compile, a Play application looks like this: -``` +```txt app → Application sources └ assets → Compiled asset sources └ stylesheets → Typically LESS CSS sources @@ -47,5 +46,3 @@ target → Generated stuff └ web → Compiled web assets test → source folder for unit or functional tests ``` - - diff --git a/docs/Scala/Play_Framework/index.html b/docs/Scala/Play_Framework/index.html deleted file mode 100644 index 9aee774..0000000 --- a/docs/Scala/Play_Framework/index.html +++ /dev/null @@ -1,2007 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Play Framework - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Play Framework

- - -

Play Framework

-

The Play application layout

-

The layout of a Play application is standardized to keep things as simple as possible. After a first successful compile, a Play application looks like this:

-
app                      → Application sources
- └ assets                → Compiled asset sources
-    └ stylesheets        → Typically LESS CSS sources
-    └ javascripts        → Typically CoffeeScript sources
- └ controllers           → Application controllers
- └ models                → Application business layer
- └ views                 → Templates
-build.sbt                → Application build script
-conf                     → Configurations files and other non-compiled resources (on classpath)
- └ application.conf      → Main configuration file
- └ routes                → Routes definition
-dist                     → Arbitrary files to be included in your projects distribution
-public                   → Public assets
- └ stylesheets           → CSS files
- └ javascripts           → Javascript files
- └ images                → Image files
-project                  → sbt configuration files
- └ build.properties      → Marker for sbt project
- └ plugins.sbt           → sbt plugins including the declaration for Play itself
-lib                      → Unmanaged libraries dependencies
-logs                     → Logs folder
- └ application.log       → Default log file
-target                   → Generated stuff
- └ resolution-cache      → Info about dependencies
- └ scala-2.11
-    └ api                → Generated API docs
-    └ classes            → Compiled class files
-    └ routes             → Sources generated from routes
-    └ twirl              → Sources generated from templates
- └ universal             → Application packaging
- └ web                   → Compiled web assets
-test                     → source folder for unit or functional tests
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Collections.md b/docs/Scala/Scala_Collections.md similarity index 61% rename from docs_src/Scala/Scala_Collections.md rename to docs/Scala/Scala_Collections.md index 051cde3..2714ef5 100644 --- a/docs_src/Scala/Scala_Collections.md +++ b/docs/Scala/Scala_Collections.md @@ -12,27 +12,30 @@ The scala package contains core types like Int, Float, Array or Option which are Notable packages include: - scala.collection and its sub-packages contain Scala's collections framework - scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet - scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet - scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap - scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet - scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet - - scala.concurrent - Primitives for concurrent programming such as Futures and Promises - scala.io - Input and output operations - scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal - scala.sys - Interaction with other processes and the operating system - scala.util.matching - Regular expressions - +```txt + scala.collection and its sub-packages contain Scala's collections framework + scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet + scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet + scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap + scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet + scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet + + scala.concurrent - Primitives for concurrent programming such as Futures and Promises + scala.io - Input and output operations + scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal + scala.sys - Interaction with other processes and the operating system + scala.util.matching - Regular expressions +``` Additional parts of the standard library are shipped as separate libraries. These include: - scala.reflect - Scala's reflection API (scala-reflect.jar) - scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar) - scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) - scala.util.parsing - Parser combinators (scala-parser-combinators.jar) - Automatic imports +```txt + scala.reflect - Scala's reflection API (scala-reflect.jar) + scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar) + scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) + scala.util.parsing - Parser combinators (scala-parser-combinators.jar) + Automatic imports +``` Identifiers in the scala package and the scala.Predef object are always in scope by default. @@ -40,19 +43,18 @@ Some of these identifiers are type aliases provided as shortcuts to commonly use Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String. - ## Traversables Traversables are the superclass of Lists, Arrays, Maps, Sets, Streams, and more. -The methods involved can be applied to each other in a different type. +The methods involved can be applied to each other in a different type. ```scala val set = Set(1, 9, 10, 22) val list = List(3, 4, 5, 10) -val result = set ++ list // ++ appends two Traversables together. +val result = set ++ list // ++ appends two Traversables together. result.size result.isEmpty -result.hasDefiniteSize // false if a Stream +result.hasDefiniteSize // false if a Stream ``` - Take some @@ -63,7 +65,7 @@ list.headOption list.tail list.lastOption result.last -list.init // collection without the last element +list.init // collection without the last element list.slice(1, 3) list.take(3) list drop 6 take 3 @@ -76,17 +78,17 @@ list.dropWhile(_ < 100) ```scala list.filter(_ < 100) list.filterNot(_ < 100) -list.find(_ % 2 != 0) // get first element that matches +list.find(_ % 2 != 0) // get first element that matches -list.foreach(num => println(num * 4)) // side effect +list.foreach(num => println(num * 4)) // side effect -list.map(_ * 4) // map +list.map(_ * 4) // map val list = List(List(1), List(2, 3, 4), List(5, 6, 7), List(8, 9, 10)) list.flatten -list.flatMap(_.map(_ * 4)) // map then flatten +list.flatMap(_.map(_ * 4)) // map then flatten -val result = list.collect { // apply a partial function to all elements of a Traversable and will return a different collection. +val result = list.collect { // apply a partial function to all elements of a Traversable and will return a different collection. case x: Int if (x % 2 == 0) => x * 3 } // can use orElse or andThen @@ -100,17 +102,17 @@ val result = array splitAt 3 result._1 result._2 -val result = array partition (_ < 100) // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not. +val result = array partition (_ < 100) // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not. // groupBy returns a map e.g. Map( "Odd" -> ... , "Even" -> ...) -val result = array groupBy { case x: Int if x % 2 == 0 => "Even"; case x: Int if x % 2 != 0 => "Odd" } +val result = array groupBy { case x: Int if x % 2 == 0 => "Even"; case x: Int if x % 2 != 0 => "Odd" } ``` - Analyze ```scala -list forall (_ < 100) // true if predicate true for all elements -list exists (_ < 100) // true if predicate true for any element +list forall (_ < 100) // true if predicate true for all elements +list exists (_ < 100) // true if predicate true for any element list count (_ < 100) ``` @@ -118,15 +120,15 @@ list count (_ < 100) ```scala list.foldLeft(0)(_ - _) -(0 /: list)(_ - _) // Short hand +(0 /: list)(_ - _) // Short hand -list.foldRight(0)(_ - _) -(list :\ 0)(_ - _) // Short hand +list.foldRight(0)(_ - _) +(list :\ 0)(_ - _) // Short hand -list.reduceLeft { _ + _ } +list.reduceLeft { _ + _ } list.reduceRight { _ + _ } -list.sum +list.sum list.product list.max list.min @@ -158,26 +160,26 @@ list.mkString(">", ",", "<") val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) stringBuilder.append("I want all numbers 6-12: ") list.filter(it => it > 5 && it < 13).addString(stringBuilder, ",") -stringBuilder.mkString +stringBuilder.mkString ``` ## Lists ```scala -val a = List(1, 2, 3) // immutable -val b = 1 :: 2 :: 3 :: Nil // cons notation -(a == b) // true -a eq b // false +val a = List(1, 2, 3) // immutable +val b = 1 :: 2 :: 3 :: Nil // cons notation +(a == b) // true +a eq b // false a.length a.head a.tail -a.reverse // reverse the list -a.map {v => v * 2} // or a.map {_ * 2} or a.map(_ * 2) +a.reverse // reverse the list +a.map {v => v * 2} // or a.map {_ * 2} or a.map(_ * 2) a.filter {v => v % 3 == 0} -a.filterNot(v => v == 5) // remove where value is 5 -a.reduceLeft(_ + _) // note the two _s below indicate the first and second args respectively -a.foldLeft(10)(_ + _) // foldlLeft is like reduce, but with an explicit starting value -(1 to 5).toList // from range +a.filterNot(v => v == 5) // remove where value is 5 +a.reduceLeft(_ + _) // note the two _s below indicate the first and second args respectively +a.foldLeft(10)(_ + _) // foldlLeft is like reduce, but with an explicit starting value +(1 to 5).toList // from range val a = a.toArray ``` @@ -192,13 +194,13 @@ if (it.hasNext) { it.next should be(__) } -val it = list grouped 3 // `grouped` will return an fixed sized Iterable chucks of an Iterable -val it = list sliding 3 // `sliding` will return an Iterable that shows a sliding window of an Iterable. -val it = list sliding(3, 3) // `sliding` can take the size of the window as well the size of the step during each iteration +val it = list grouped 3 // `grouped` will return an fixed sized Iterable chucks of an Iterable +val it = list sliding 3 // `sliding` will return an Iterable that shows a sliding window of an Iterable. +val it = list sliding(3, 3) // `sliding` can take the size of the window as well the size of the step during each iteration list takeRight 3 list dropRight 3 -val xs = List(3, 5, 9) // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables. +val xs = List(3, 5, 9) // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables. val ys = List("Bob", "Ann", "Stella") xs zip ys @@ -230,7 +232,7 @@ s.toList ```scala val strictList = List(10, 20, 30) -val lazyList = strictList.view // Strict collection always processes its elements but lazy collection does it on demand +val lazyList = strictList.view // Strict collection always processes its elements but lazy collection does it on demand val infinite = Stream.from(1) infinite.take(4).sum @@ -251,15 +253,15 @@ stream.head val myMap = Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "MI" -> "Michigan") // access by key - Accessing a map by key results in an exception if key is not found -myMap("MI") -myMap.contains("IL") +myMap("MI") +myMap.contains("IL") val aNewMap = myMap + ("IL" -> "Illinois") // add - creates a new collection if immutable -val aNewMap = myMap - "MI" // remove - Attempted removal of nonexistent elements from a map is handled gracefully +val aNewMap = myMap - "MI" // remove - Attempted removal of nonexistent elements from a map is handled gracefully val aNewMap = myMap -- List("MI", "OH") // remove multiples val aNewMap = myMap - ("MI", "WI") // Notice: single '-' operator for tuples -var anotherMap += ("IL" -> "Illinois") // compiler trick - creates a new collection and reassigns; note the 'var' +var anotherMap += ("IL" -> "Illinois") // compiler trick - creates a new collection and reassigns; note the 'var' // Map values can be iterated val mapValues = myMap.values @@ -292,8 +294,8 @@ Maps insertion with duplicate key updates previous entry with subsequent value ```scala val myMap = mutable.Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "IA" -> "Iowa") // same methods than immutable maps work -val myMap += ("IL" -> "Illinois") // this is a method; note the difference from immutable += -myMap.clear() // Convention is to use parens if possible when method called changes state +val myMap += ("IL" -> "Illinois") // this is a method; note the difference from immutable += +myMap.clear() // Convention is to use parens if possible when method called changes state ``` ## Sets @@ -311,9 +313,9 @@ mySet --= List("Iowa", "Ohio") mySet.clear() // mutable only var sum = 0 -for (i <- mySet) // for comprehension - sum = sum + i // of course this is the same thing as mySet.reduce(_ + _) - +for (i <- mySet) // for comprehension + sum = sum + i // of course this is the same thing as mySet.reduce(_ + _) + val mySet2 = Set("Wisconsin", "Michigan", "Minnesota") mySet intersect mySet2 // or & operator mySet1 union mySet2 // or | operator @@ -327,11 +329,11 @@ mySet1.equals(mySet2) // independent of order ```scala val someValue: Option[String] = Some("I am wrapped in something") val nullValue: Option[String] = None -someValue.get // java.util.NoSuchElementException if None -nullValue getOrElse "No value" +someValue.get // java.util.NoSuchElementException if None +nullValue getOrElse "No value" nullValue.isEmpty -val value = someValue match { // pattern matching +val value = someValue match { // pattern matching case Some(v) => v case None => 0.0 } @@ -342,7 +344,7 @@ val value = someValue match { // pattern matching ```scala Some(10) filter { _ == 10} Some(Some(10)) flatMap { _ map { _ + 10}} - var newValue1 = 0 + var newValue1 = 0 Some(20) foreach { newValue1 = _} ``` @@ -365,7 +367,7 @@ val result = list.flatMap(it => if (it % 2 == 0) Some(it) else None) ## Java Interop -Scala can implicitly convert from a Scala collection type into a Java collection type. +Scala can implicitly convert from a Scala collection type into a Java collection type. ```scala import scala.collection.JavaConversions._ diff --git a/docs/Scala/Scala_Collections/index.html b/docs/Scala/Scala_Collections/index.html deleted file mode 100644 index 89644a9..0000000 --- a/docs/Scala/Scala_Collections/index.html +++ /dev/null @@ -1,2417 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Collections - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Scala Collections

- -

Examples from Scala Koans.

-

Core Packages

-

The scala package contains core types like Int, Float, Array or Option which are accessible in all Scala compilation units without explicit qualification or imports.

-

Notable packages include:

-
scala.collection and its sub-packages contain Scala's collections framework
-scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet
-scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet
-scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap
-scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet
-scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet
-
-scala.concurrent - Primitives for concurrent programming such as Futures and Promises
-scala.io - Input and output operations
-scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal
-scala.sys - Interaction with other processes and the operating system
-scala.util.matching - Regular expressions
-
- -

Additional parts of the standard library are shipped as separate libraries. These include:

-
scala.reflect - Scala's reflection API (scala-reflect.jar)
-scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar)
-scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar)
-scala.util.parsing - Parser combinators (scala-parser-combinators.jar)
-Automatic imports
-
- -

Identifiers in the scala package and the scala.Predef object are always in scope by default.

-

Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.List.

-

Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String.

-

Traversables

-

Traversables are the superclass of Lists, Arrays, Maps, Sets, Streams, and more. -The methods involved can be applied to each other in a different type.

-
val set = Set(1, 9, 10, 22)
-val list = List(3, 4, 5, 10)
-val result = set ++ list        // ++ appends two Traversables together.
-result.size
-result.isEmpty
-result.hasDefiniteSize          // false if a Stream
-
- -
    -
  • Take some
  • -
-
list.head
-list.headOption
-list.tail
-list.lastOption
-result.last
-list.init                       // collection without the last element
-list.slice(1, 3)
-list.take(3)
-list drop 6 take 3
-list.takeWhile(_ < 100)
-list.dropWhile(_ < 100)
-
- -
    -
  • Filter, Map, Flatten
  • -
-
list.filter(_ < 100)
-list.filterNot(_ < 100)
-list.find(_ % 2 != 0)                       // get first element that matches
-
-list.foreach(num => println(num * 4))       // side effect
-
-list.map(_ * 4)                             // map
-
-val list = List(List(1), List(2, 3, 4), List(5, 6, 7), List(8, 9, 10))
-list.flatten
-list.flatMap(_.map(_ * 4))                  // map then flatten
-
-val result = list.collect {                 // apply a partial function to all elements of a Traversable and will return a different collection.
-      case x: Int if (x % 2 == 0) => x * 3
-    }
-// can use  orElse  or andThen
-
- -
    -
  • Split
  • -
-
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)  // splitAt - will split a Traversable at a position, returning a tuple.
-val result = array splitAt 3
-result._1
-result._2
-
-val result = array partition (_ < 100)              // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not.  
-
-// groupBy returns a map e.g. Map( "Odd" -> ... , "Even" -> ...)
-val result = array groupBy { case x: Int if x % 2 == 0 => "Even"; case x: Int if x % 2 != 0 => "Odd" } 
-
- -
    -
  • Analyze
  • -
-
list forall (_ < 100)                       // true if predicate true for all elements
-list exists (_ < 100)                       // true if predicate true for any element
-list count (_ < 100)
-
- -
    -
  • Reduce and Fold
  • -
-
list.foldLeft(0)(_ - _)
-(0 /: list)(_ - _)                          // Short hand
-
-list.foldRight(0)(_ - _)                
-(list :\ 0)(_ - _)                          // Short hand
-
-list.reduceLeft { _ + _ } 
-list.reduceRight { _ + _ }
-
-list.sum 
-list.product
-list.max
-list.min
-
-val list = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
-list.transpose
-
- -
    -
  • Conversions; toList, as well as other conversion methods like toSet, toArray will not convert if the collection type is the same.
  • -
-
list.toArray
-list.toSet
-set.toList
-set.toIterable
-set.toSeq
-set.toIndexedSeq
-list.toStream
-
-val list = List("Phoenix" -> "Arizona", "Austin" -> "Texas")  // elements should be tuples
-val result = list.toMap
-
- -
    -
  • Print
  • -
-
result.mkString(",")
-list.mkString(">", ",", "<")
-val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
-stringBuilder.append("I want all numbers 6-12: ")
-list.filter(it => it > 5 && it < 13).addString(stringBuilder, ",")
-stringBuilder.mkString 
-
- -

Lists

-
val a = List(1, 2, 3)       // immutable
-val b = 1 :: 2 :: 3 :: Nil  // cons notation 
-(a == b)    // true
-a eq b      // false
-a.length
-a.head
-a.tail
-a.reverse                   // reverse the list
-a.map {v => v * 2}          // or a.map {_ * 2} or a.map(_ * 2)
-a.filter {v => v % 3 == 0}
-a.filterNot(v => v == 5)    // remove where value is 5
-a.reduceLeft(_ + _)         // note the two _s below indicate the first and second args respectively
-a.foldLeft(10)(_ + _)       // foldlLeft is like reduce, but with an explicit starting value
-(1 to 5).toList             // from range
-val a = a.toArray
-
- -

Nil lists are identical, even of different types

-

Iterators

-
val list = List(3, 5, 9, 11, 15, 19, 21)
-val it = list.iterator
-if (it.hasNext) {
-  it.next should be(__)
-}
-
-val it = list grouped 3         // `grouped` will return an fixed sized Iterable chucks of an Iterable
-val it = list sliding 3         // `sliding` will return an Iterable that shows a sliding window of an Iterable.    
-val it = list sliding(3, 3)     // `sliding` can take the size of the window as well the size of the step during each iteration
-list takeRight 3
-list dropRight 3
-
-val xs = List(3, 5, 9)          // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables.
-val ys = List("Bob", "Ann", "Stella")
-xs zip ys
-
-// If two Iterables aren't the same size, then `zip` will only zip what can only be paired.
-xs zipAll(ys, -1, "?")  // if two Iterables aren't the same size, then `zipAll` can provide fillers
-
-xs.zipWithIndex
-
- -

Arrays, Sequences

-
val a = Array(1, 2, 3)
-val s = a.toSeq
-val l = s.toList
-
- -
val s = Seq("hello", "to", "you")
-val filtered = s.filter(_.length > 2)
-val r = s map {
-      _.reverse
-    }
-val s = for (v <- 1 to 10 if v % 3 == 0) yield v  // create a sequence from a for comprehension with an optional condition
-s.toList
-
- -

Lazy Collections and Streams

-
val strictList = List(10, 20, 30)
-val lazyList = strictList.view      // Strict collection always processes its elements but lazy collection does it on demand
-
-val infinite = Stream.from(1)
-infinite.take(4).sum
-Stream.continually(1).take(4).sum
-
-// Always remember tail of a lazy collection is never computed unless required
-
-def makeLazy(value: Int): Stream[Int] = {
-  Stream.cons(value, makeLazy(value + 1))
-}
-val stream = makeLazy(1)
-stream.head
-
- -

Maps

-
val myMap = Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "MI" -> "Michigan")
-
-// access by key - Accessing a map by key results in an exception if key is not found
-myMap("MI")                                 
-myMap.contains("IL") 
-
-val aNewMap = myMap + ("IL" -> "Illinois")  // add - creates a new collection if immutable
-val aNewMap = myMap - "MI"                  // remove - Attempted removal of nonexistent elements from a map is handled gracefully
-val aNewMap = myMap -- List("MI", "OH")     // remove multiples
-val aNewMap = myMap - ("MI", "WI") // Notice: single '-' operator for tuples
-
-var anotherMap += ("IL" -> "Illinois")      // compiler trick - creates a new collection and reassigns; note the 'var' 
-
-// Map values can be iterated
-val mapValues = myMap.values
-mapValues.size
-mapValues.head
-mapValues.last
-
-for (mval <- mapValues) println(mval)
-// NOTE that the following will not compile, as iterators do not implement "contains"
-//mapValues.contains("Illinois")
-
-// Map keys may be of mixed type
-val myMap = Map("Ann Arbor" -> "MI", 49931 -> "MI")
-
-// Mixed type values can be added to a map
-val myMap = scala.collection.mutable.Map.empty[String, Any]
-myMap("Ann Arbor") = (48103, 48104, 48108)
-myMap("Houghton") = 49931
-
-// Map equivalency is independent of order
-val myMap1 = Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "IA" -> "Iowa")
-val myMap2 = Map("WI" -> "Wisconsin", "MI" -> "Michigan", "IA" -> "Iowa", "OH" -> "Ohio")
-myMap1.equals(myMap2)
-
- -

Maps insertion with duplicate key updates previous entry with subsequent value

-
    -
  • Mutable Maps
  • -
-
val myMap = mutable.Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "IA" -> "Iowa")
-// same methods than immutable maps work
-val myMap += ("IL" -> "Illinois")       // this is a method; note the difference from immutable += 
-myMap.clear()                           // Convention is to use parens if possible when method called changes state
-
- -

Sets

-
val mySet = Set(1, 3, 4, 9)  // immutable
-val mySet = mutable.Set("Michigan", "Ohio", "Wisconsin", "Iowa")
-mySet.size
-mySet contains "Ohio"
-mySet += "Oregon"
-mySet += ("Iowa", "Ohio")
-mySet ++= List("Iowa", "Ohio")
-mySet -= "Ohio"
-mySet --= List("Iowa", "Ohio")
-mySet.clear()  // mutable only
-
-var sum = 0
-for (i <- mySet)    // for comprehension
-  sum = sum + i     // of course this is the same thing as mySet.reduce(_ + _)
-
-val mySet2 = Set("Wisconsin", "Michigan", "Minnesota")
-mySet intersect mySet2  // or & operator
-mySet1 union mySet2    // or | operator
-mySet2 subsetOf mySet1
-mySet1 diff mySet2
-mySet1.equals(mySet2)  // independent of order
-
- -

Option[T]

-
val someValue: Option[String] = Some("I am wrapped in something")
-val nullValue: Option[String] = None
-someValue.get                       // java.util.NoSuchElementException if None
-nullValue getOrElse "No value" 
-nullValue.isEmpty
-
-val value = someValue match {       // pattern matching
-      case Some(v) => v
-      case None => 0.0
-    }
-
- -
    -
  • Option is more than just a replacement of null, its also a collection.
  • -
-
    Some(10) filter { _ == 10}
-    Some(Some(10)) flatMap { _ map { _ + 10}}
-    var newValue1 = 0
-    Some(20) foreach { newValue1 = _}
-
- -
    -
  • flatMap of Options will filter out all Nones and keep the Somes
  • -
-
val list = List(1, 2, 3, 4, 5)
-val result = list.flatMap(it => if (it % 2 == 0) Some(it) else None)
-
- -
    -
  • Using "for comprehension"
  • -
-
    val values = List(Some(10), Some(20), None, Some(15))
-    val newValues = for {
-      someValue <- values
-      value <- someValue
-    } yield value
-
- -

Java Interop

-

Scala can implicitly convert from a Scala collection type into a Java collection type.

-
import scala.collection.JavaConversions._
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Database_Access.md b/docs/Scala/Scala_Database_Access.md similarity index 51% rename from docs_src/Scala/Scala_Database_Access.md rename to docs/Scala/Scala_Database_Access.md index 128f74f..78a2d80 100644 --- a/docs_src/Scala/Scala_Database_Access.md +++ b/docs/Scala/Scala_Database_Access.md @@ -6,24 +6,23 @@ tags: Scala, DB ## Database Access / ORM Libraries -[Slick](http://slick.lightbend.com/) +[Slick](https://slick.lightbend.com/) -* [Manual](http://slick.lightbend.com/doc/3.2.1/introduction.html) - -[JOOQ](http://www.jooq.org/) +* [Manual](https://slick.lightbend.com/doc/3.2.1/introduction.html) -[Squeryl](http://squeryl.org/getting-started.html) +[JOOQ](https://www.jooq.org/) -[SORM](http://sorm-framework.org/) +[Squeryl](https://squeryl.org/getting-started.html) + +[SORM](https://sorm-framework.org/) [Doobie](https://tpolecat.github.io/doobie/) -[ReactiveMongo](http://reactivemongo.org/) +[ReactiveMongo](https://reactivemongo.org/) [Comparison of multiple frameworks]( https://softwaremill.com/comparing-scala-relational-database-access-libraries/#summary) - ## Database Initialization / Migration -[Flyway](https://flywaydb.org/) \ No newline at end of file +[Flyway](https://flywaydb.org/) diff --git a/docs/Scala/Scala_Database_Access/index.html b/docs/Scala/Scala_Database_Access/index.html deleted file mode 100644 index fea8707..0000000 --- a/docs/Scala/Scala_Database_Access/index.html +++ /dev/null @@ -1,1983 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Database Access - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Design_Patterns.md b/docs/Scala/Scala_Design_Patterns.md similarity index 88% rename from docs_src/Scala/Scala_Design_Patterns.md rename to docs/Scala/Scala_Design_Patterns.md index 274f064..50e166b 100644 --- a/docs_src/Scala/Scala_Design_Patterns.md +++ b/docs/Scala/Scala_Design_Patterns.md @@ -6,12 +6,11 @@ tags: Scala, Design Patterns ## Create a new project from template -Use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. +Use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. You can find a list of templates [here](https://github.com/foundweekends/giter8/wiki/giter8-templates/30ac1007438f6f7727ea98c19db1f82ea8f00ac8). Or download from [Scala Project Templates](https://developer.lightbend.com/start/) - ## Static Factory ```scala @@ -49,23 +48,22 @@ case class B() extends A case class C() extends A ``` -They have only data and do not contain any functionality on top of this data as normal classes would. +They have only data and do not contain any functionality on top of this data as normal classes would. ```scala -sealed trait Shape -case class Circle(radius: Double) extends Shape +sealed trait Shape +case class Circle(radius: Double) extends Shape case class Rectangle(height: Double, width: Double) extends Shape -object Shape { - def area(shape: Shape): Double = - shape match { +object Shape { + def area(shape: Shape): Double = + shape match { case Circle(Point(x, y), radius) => Math.PI * Math.pow(radius, 2) // use pattern matching to process - case Rectangle(_, h, w) => h * w - } + case Rectangle(_, h, w) => h * w + } } ``` - ## Stackable Traits ```scala @@ -100,19 +98,19 @@ object Example { _Stackable traits order of execution_ -Stackable traits are always executed from the right mixin to the left. +Stackable traits are always executed from the right mixin to the left. Sometimes, however, if we only get output and it doesn't depend on what is passed to the method, we simply end up with method calls on a stack, which then get evaluated and it will appear as if things are applied from left to right. ## Components / Cake Pattern -[http://jonasboner.com/real-world-scala-dependency-injection-di/](http://jonasboner.com/real-world-scala-dependency-injection-di/) +[https://jonasboner.com/real-world-scala-dependency-injection-di/](https://jonasboner.com/real-world-scala-dependency-injection-di/) ```scala // Service Interfaces and Component Definitions trait OnOffDeviceComponent { val onOff: OnOffDevice // abstract val - + trait OnOffDevice { def on: Unit def off: Unit @@ -121,7 +119,7 @@ trait OnOffDeviceComponent { trait SensorDeviceComponent { val sensor: SensorDevice - + trait SensorDevice { def isCoffeePresent: Boolean } @@ -156,14 +154,14 @@ trait WarmerComponentImpl { } // ======================= -// Instantiation (and configuration) of the services in the ComponentRegistry module +// Instantiation (and configuration) of the services in the ComponentRegistry module object ComponentRegistry extends OnOffDeviceComponentImpl with SensorDeviceComponentImpl with WarmerComponentImpl { - val onOff = new Heater // all instantiations in one spot; can be easily be replaced by e.g. mocks + val onOff = new Heater // all instantiations in one spot; can be easily be replaced by e.g. mocks val sensor = new PotSensor val warmer = new Warmer } @@ -181,7 +179,7 @@ warmer.trigger - Concerns that cross class hierarchy e.g. serialize to JSON - Common behaviour without (useful) common type - Abstract behaviour to a type class -- Can implement type class instances in ad-hoc manner +- Can implement type class instances in ad-hoc manner ```scala // Define some behavior in terms of operations that a type must support in order to be considered a member of the type class. @@ -193,21 +191,21 @@ trait Number[T] { // Define the default type class members in the companion object of the trait object Number { - implicit object DoubleNumber extends Number[Double] { // note the implicit + implicit object DoubleNumber extends Number[Double] { // note the implicit override def plus(x: Double, y: Double): Double = x + y override def divide(x: Double, y: Int): Double = x / y } -} - +} + object Stats { // older pattern with implicit parameter -// def mean[T](xs: Vector[T])(implicit ev: Number[T]): T = // note the implicit +// def mean[T](xs: Vector[T])(implicit ev: Number[T]): T = // note the implicit // ev.divide(xs.reduce(ev.plus(_, _)), xs.size) - - def mean[T: Number](xs: Vector[T]): T = // note the context bound + + def mean[T: Number](xs: Vector[T]): T = // note the context bound implicitly[Number[T]].divide( - xs.reduce(implicitly[Number[T]].plus(_, _)), // retrieve the evidence via implicitly[] + xs.reduce(implicitly[Number[T]].plus(_, _)), // retrieve the evidence via implicitly[] xs.size ) } @@ -242,13 +240,13 @@ trait Visitor { def visit(element: Element) } -class VisitorImpl1 extends Visitor { +class VisitorImpl1 extends Visitor { override def visit(element: Element): Unit = { element match { case Title(text) => ??? - case Text(text) => ??? - //... - } + case Text(text) => ??? + //... + } } } ``` @@ -261,17 +259,17 @@ import com.typesafe.config.ConfigFactory trait AppConfigComponent { val appConfigService: AppConfigService - + class AppConfigService() { //-Dconfig.resource=production.conf for overriding private val conf = ConfigFactory.load() private val appConf = conf.getConfig("job-scheduler") private val db = appConf.getConfig("db") - + val configPath = appConf.getString("config-path") val configExtension = appConf.getString("config-extension") val workers = appConf.getInt("workers") - + val dbConnectionString = db.getString("connection-string") val dbUsername = db.getString("username") val dbPassword = db.getString("password") @@ -294,7 +292,7 @@ trait Memoizer { ``` Using scalaz: - + ```scala val memoScalaz: String => String = Memo.mutableHashMapMemo { func @@ -309,13 +307,13 @@ The pimp my library design pattern is really similar to extension methods in C#. package object pimp { implicit class StringExtensions(val s: String) extends AnyVal { - + def isAllUpperCase: Boolean = (0 to s.size - 1).find { case index => !s.charAt(index).isUpper }.isEmpty - + } } ``` diff --git a/docs/Scala/Scala_Design_Patterns/index.html b/docs/Scala/Scala_Design_Patterns/index.html deleted file mode 100644 index ff9fc01..0000000 --- a/docs/Scala/Scala_Design_Patterns/index.html +++ /dev/null @@ -1,2367 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Design Patterns - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Scala Design Patterns

- -

Create a new project from template

-

Use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. -You can find a list of templates here.

-

Or download from Scala Project Templates

-

Static Factory

-
trait Animal
-class Bird extends Animal
-class Mammal extends Animal
-class Fish extends Animal
-
-object Animal {
-  def apply(animal: String): Animal = animal.toLowerCase match {
-    case "bird" => new Bird
-    case "mammal" => new Mammal
-    case "fish" => new Fish
-    case x: String => throw new RuntimeException(s"Unknown animal: $x")
-  }
-}
-
- -

Algebraic Data Types and Pattern Matching

-
    -
  • Goal: translate data descriptions into code
  • -
  • Model data with logical ors and logical ands
  • -
  • Two patterns: product types (and) sum types (or)
  • -
  • Product type: A has a B and C
  • -
  • Sum type: A is a B or C
  • -
  • Sum and product together make algebraic data types
  • -
-
// A has a B and C
-case class A(b: B, c: C)
-
-// A is a B or C
-sealed trait A
-case class B() extends A
-case class C() extends A
-
- -

They have only data and do not contain any functionality on top of this data as normal classes would.

-
sealed trait Shape 
-case class Circle(radius: Double) extends Shape 
-case class Rectangle(height: Double, width: Double) extends Shape
-
-object Shape { 
-  def area(shape: Shape): Double = 
-    shape match { 
-      case Circle(Point(x, y), radius) => Math.PI * Math.pow(radius, 2)   // use pattern matching to process
-      case Rectangle(_, h, w) => h * w 
-    } 
-}
-
- -

Stackable Traits

-
abstract class StringWriter {
-  def write(data: String): String
-}
-
-class BasicStringWriter extends StringWriter {
-  override def write(data: String): String =
-    s"Writing the following data: ${data}"
-}
-
-trait CapitalizingStringWriter extends StringWriter {
-  abstract override def write(data: String): String = {
-    super.write(data.split("\\s+").map(_.capitalize).mkString(" "))
-  }
-}
-
-trait UppercasingStringWriter extends StringWriter {
-  abstract override def write(data: String): String = {
-    super.write(data.toUpperCase)
-  }
-}
-
-object Example {
-  def main(args: Array[String]): Unit = {
-    val writer1 = new BasicStringWriter with UppercasingStringWriter with CapitalizingStringWriter
-    System.out.println(s"Writer 1: '${writer1.write("we like learning scala!")}'")
-  }
-}
-
- -

Stackable traits order of execution

-

Stackable traits are always executed from the right mixin to the left. -Sometimes, however, if we only get output and it doesn't depend on what is passed to the method, we simply end up with method calls on a stack, which then get evaluated and it will appear as if things are applied from left to right.

-

Components / Cake Pattern

-

http://jonasboner.com/real-world-scala-dependency-injection-di/

-
// Service Interfaces and Component Definitions
-
-trait OnOffDeviceComponent {
-  val onOff: OnOffDevice  // abstract val
-
-  trait OnOffDevice {
-    def on: Unit
-    def off: Unit
-  }
-}
-
-trait SensorDeviceComponent {
-  val sensor: SensorDevice
-
-  trait SensorDevice {
-    def isCoffeePresent: Boolean
-  }
-}
-
-// =======================
-// Component / Service Implementations
-
-trait OnOffDeviceComponentImpl extends OnOffDeviceComponent {
-  class Heater extends OnOffDevice {
-    def on = println("heater.on")
-    def off = println("heater.off")
-  }
-}
-
-trait SensorDeviceComponentImpl extends SensorDeviceComponent {
-  class PotSensor extends SensorDevice {
-    def isCoffeePresent = true
-  }
-}
-
-// =======================
-// Component declaring two dependencies that it wants injected
-trait WarmerComponentImpl {
-  this: SensorDeviceComponent with OnOffDeviceComponent =>     // Use of self-type for composition
-  class Warmer {
-    def trigger = {
-      if (sensor.isCoffeePresent) onOff.on
-      else onOff.off
-    }
-  }
-}
-
-// =======================
-// Instantiation (and configuration) of the services in the ComponentRegistry module 
-
-object ComponentRegistry extends
-  OnOffDeviceComponentImpl with
-  SensorDeviceComponentImpl with
-  WarmerComponentImpl {
-
-  val onOff = new Heater      // all instantiations in one spot; can be easily be replaced by e.g. mocks 
-  val sensor = new PotSensor
-  val warmer = new Warmer
-}
-
-// =======================
-val warmer = ComponentRegistry.warmer
-warmer.trigger
-
- -

Type Classes (using context-bound type parameters)

-
    -
  • Ad-hoc polymorphism
  • -
  • Break free from your class oppressors!
  • -
  • Concerns that cross class hierarchy e.g. serialize to JSON
  • -
  • Common behaviour without (useful) common type
  • -
  • Abstract behaviour to a type class
  • -
  • Can implement type class instances in ad-hoc manner
  • -
-
// Define some behavior in terms of operations that a type must support in order to be considered a member of the type class.
-trait Number[T] {
-  def plus(x: T, y: T): T
-  def divide(x: T, y: Int): T
-}
-
-// Define the default type class members in the companion object of the trait
-object Number {
-
-  implicit object DoubleNumber extends Number[Double] {             // note the implicit
-    override def plus(x: Double, y: Double): Double = x + y
-    override def divide(x: Double, y: Int): Double = x / y
-  }
-} 
-
-object Stats {
-
-//  older pattern with implicit parameter
-//  def mean[T](xs: Vector[T])(implicit ev: Number[T]): T =         // note the implicit
-//    ev.divide(xs.reduce(ev.plus(_, _)), xs.size)
-
-  def mean[T: Number](xs: Vector[T]): T =                           // note the context bound
-    implicitly[Number[T]].divide(
-      xs.reduce(implicitly[Number[T]].plus(_, _)),                  // retrieve the evidence via implicitly[]
-      xs.size
-    )
-}
-
- -

Visitor Pattern

-
abstract class Element(text: String) {
-  def accept(visitor: Visitor)
-}
-
-case class Title(text: String) extends Element(text) {
-  override def accept(visitor: Visitor): Unit = {
-    visitor.visit(this)
-  }
-}
-
-case class Text(text: String) extends Element(text) {
-  override def accept(visitor: Visitor): Unit = {
-    visitor.visit(this)
-  }
-}
-
-class Document(parts: List[Element]) {
-  def accept(visitor: Visitor): Unit = {
-    parts.foreach(p => p.accept(visitor))
-  }
-}
-
-trait Visitor {
-  def visit(element: Element)
-}
-
-class VisitorImpl1 extends Visitor { 
-  override def visit(element: Element): Unit = {
-    element match {
-      case Title(text) => ???
-      case Text(text) => ??? 
-      //...
-      }
-  }
-}
-
- -

Configuration

-
import com.typesafe.config.ConfigFactory
-
-trait AppConfigComponent {
-
-  val appConfigService: AppConfigService
-
-  class AppConfigService() {
-    //-Dconfig.resource=production.conf for overriding
-    private val conf = ConfigFactory.load()
-    private val appConf = conf.getConfig("job-scheduler")
-    private val db = appConf.getConfig("db")
-
-    val configPath = appConf.getString("config-path")
-    val configExtension = appConf.getString("config-extension")
-    val workers = appConf.getInt("workers")
-
-    val dbConnectionString = db.getString("connection-string")
-    val dbUsername = db.getString("username")
-    val dbPassword = db.getString("password")
-  }
-}
-
- -

Memoization

-
import scala.collection.mutable.Map
-
-trait Memoizer {
-
-  def memo[X, Y](f: X => Y): (X => Y) = {
-    val cache = Map[X, Y]()
-    (x: X) => cache.getOrElseUpdate(x, f(x))
-  }
-}
-
- -

Using scalaz:

-
val memoScalaz: String => String = Memo.mutableHashMapMemo {
-  func
-}
-
- -

Pimp my Library Pattern

-

The pimp my library design pattern is really similar to extension methods in C#.

-
package object pimp {
-
-  implicit class StringExtensions(val s: String) extends AnyVal {
-
-    def isAllUpperCase: Boolean =
-      (0 to s.size - 1).find {
-        case index =>
-          !s.charAt(index).isUpper
-      }.isEmpty
-
-  }
-}
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Generalities.md b/docs/Scala/Scala_Generalities.md similarity index 78% rename from docs_src/Scala/Scala_Generalities.md rename to docs/Scala/Scala_Generalities.md index f43e2a0..1a6b1f8 100644 --- a/docs_src/Scala/Scala_Generalities.md +++ b/docs/Scala/Scala_Generalities.md @@ -15,26 +15,24 @@ tags: Scala - Closures - Concurrency support inspired by Erlang - ## Tools and Frameworks -REPL [http://ammonite.io/](http://ammonite.io/) +REPL [https://ammonite.io/](https://ammonite.io/) [https://scalafiddle.io/](https://scalafiddle.io/) - [The Lift Framework]( https://liftweb.net/ ) - [The Play framework]( https://www.playframework.com/ ) - [The Bowler framework]( https://github.com/bowler-framework/bowler-quickstart ) -- [Akka]( http://akka.io/ ) +- [Akka]( https://akka.io/ ) [https://typelevel.org/](https://typelevel.org/) - ## Install -* Need to have Java Software Development Kit (SDK) installed +- Need to have Java Software Development Kit (SDK) installed -``` +```bash java -version ``` @@ -43,7 +41,7 @@ export JAVA_HOME=/usr/local/java-current export PATH=$PATH:$JAVA_HOME/bin/ ``` -[http://www.scala-lang.org/download/](http://www.scala-lang.org/download/) +[https://www.scala-lang.org/download/](https://www.scala-lang.org/download/) ### Compilation diff --git a/docs/Scala/Scala_Generalities/index.html b/docs/Scala/Scala_Generalities/index.html deleted file mode 100644 index d322a2a..0000000 --- a/docs/Scala/Scala_Generalities/index.html +++ /dev/null @@ -1,2047 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala (Generalities) - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Scala (Generalities)

- -

Main Features of Scala

-
    -
  • All types are objects
  • -
  • Type inference
  • -
  • Nested Functions
  • -
  • Functions are objects
  • -
  • Domain specific language (DSL) support
  • -
  • Traits
  • -
  • Closures
  • -
  • Concurrency support inspired by Erlang
  • -
-

Tools and Frameworks

-

REPL http://ammonite.io/

-

https://scalafiddle.io/

- -

https://typelevel.org/

-

Install

-
    -
  • Need to have Java Software Development Kit (SDK) installed
  • -
-
java -version
-
- -
export JAVA_HOME=/usr/local/java-current
-export PATH=$PATH:$JAVA_HOME/bin/
-
- -

http://www.scala-lang.org/download/

-

Compilation

-
scalac HelloWorld.scala  // produces HelloWorld.class
-scala -classpath . HelloWorld
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Language.md b/docs/Scala/Scala_Language.md similarity index 80% rename from docs_src/Scala/Scala_Language.md rename to docs/Scala/Scala_Language.md index 4c5a477..dfd2d4a 100644 --- a/docs_src/Scala/Scala_Language.md +++ b/docs/Scala/Scala_Language.md @@ -4,14 +4,13 @@ category: Scala tags: Scala --- - ## Links -- [Scala Cheatsheet]( http://docs.scala-lang.org/cheatsheets/ ) +- [Scala Cheatsheet]( https://docs.scala-lang.org/cheatsheets/ ) - [Scala @ TutorialPoint]( https://www.tutorialspoint.com/scala/index.htm ) -- [Scala Tutorial (PDF)]( http://www.scala-lang.org/docu/files/ScalaTutorial.pdf ) +- [Scala Tutorial (PDF)]( https://www.scala-lang.org/docu/files/ScalaTutorial.pdf ) -Some examples are derived from [Scala Koans](http://www.scalakoans.org/). +Some examples are derived from [Scala Koans](https://www.scalakoans.org/). ## Basics @@ -29,25 +28,25 @@ Program File Name - Name of the program file should exactly match the object nam Assume 'HelloWorld' is the object name: the file should be saved as 'HelloWorld.scala'. - ### Packages ```scala -package pkg // at start of file -package pkg { ... } // bracket style +package pkg // at start of file +package pkg { ... } // bracket style ``` ### Imports ```scala -import scala.collection._ // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*). +import scala.collection._ // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*). import scala.collection.Vector // one class import -import scala.collection.{Vector, Sequence} // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces -import scala.collection.{Vector => Vec28} // renaming import. -import java.util.{Date => _, _} // import all from java.util except Date. +import scala.collection.{Vector, Sequence} // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces +import scala.collection.{Vector => Vec28} // renaming import. +import java.util.{Date => _, _} // import all from java.util except Date. ``` All classes from the java.lang package are imported by default. The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification: + - immutable Map, Set, List, ::, Nil, print, println, assert, assume, require, ensuring ```scala @@ -95,21 +94,21 @@ lazy val a = {heavymath(); 19} ### Literals ```scala -val a = 2 // int +val a = 2 // int val b = 31L // long val c = 0x30B // hexadecimal -val d = 3f // float -val e = 3.22d // double +val d = 3f // float +val e = 3.22d // double val f = 93e-9 -val g = 'a' // character -val h = '\u0061' // unicode for a -val i = '\141' // octal for a -val j = '\"' // escape sequences +val g = 'a' // character +val h = '\u0061' // unicode for a +val i = '\141' // octal for a +val j = '\"' // escape sequences val k = '\\' -val s = "To be or not to be" // string +val s = "To be or not to be" // string s.charAt(0) val s2 = """An apple a day -keeps the doctor away""" // multi-lines string +keeps the doctor away""" // multi-lines string s2.split('\n') val s3 = """An apple a day |keeps the doctor away""" // Multiline String literals can use | to specify the starting position of subsequent lines, then use stripMargin to remove the surplus indentation. @@ -151,57 +150,57 @@ object GreekPlanets extends Enumeration { ### Common Data Structures ```scala -(1,2,3) // tuple literal. (Tuple3) -var (x,y,z) = (1,2,3) // destructuring bind: tuple unpacking via pattern matching. -// BAD var x,y,z = (1,2,3) // hidden error: each assigned to the entire tuple. +(1,2,3) // tuple literal. (Tuple3) +var (x,y,z) = (1,2,3) // destructuring bind: tuple unpacking via pattern matching. +// BAD var x,y,z = (1,2,3) // hidden error: each assigned to the entire tuple. -val tuple = ("apple", 3) // mixed type tuple +val tuple = ("apple", 3) // mixed type tuple tuple._1 tuple._2 tuple.swap ``` ```scala -var xs = List(1,2,3) // list (immutable). -xs(2) // paren indexing -1 :: List(2,3) // cons (create a new list by prepending the element). +var xs = List(1,2,3) // list (immutable). +xs(2) // paren indexing +1 :: List(2,3) // cons (create a new list by prepending the element). -1 to 5 // Range sugar. Same as `1 until 6` +1 to 5 // Range sugar. Same as `1 until 6` 1 to 10 by 2 -Range(1, 10, 2) // Range does not include the last item, even in a step increment +Range(1, 10, 2) // Range does not include the last item, even in a step increment Range(1, 9, 2).inclusive ``` ```scala -() // (empty parens) sole member of the Unit type (like C/Java void). +() // (empty parens) sole member of the Unit type (like C/Java void). ``` ### Control Constructs ```scala -if (check) happy else sad // conditional. +if (check) happy else sad // conditional. if (check) happy // -if (check) happy else () // same as above -while (x < 5) { println(x); x += 1} // while loop. -do { println(x); x += 1} while (x < 5) // do while loop. - -for (x <- xs if x%2 == 0) yield x*10 // for comprehension with guard -xs.filter(_%2 == 0).map(_*10) // same as filter/map -for ((x,y) <- xs zip ys) yield x*y // for comprehension: destructuring bind -(xs zip ys) map { case (x,y) => x*y } // same as -for (x <- xs; y <- ys) yield x*y // for comprehension: cross product. Later generators varying more rapidly than earlier ones -xs flatMap {x => ys map {y => x*y}} // same as +if (check) happy else () // same as above +while (x < 5) { println(x); x += 1} // while loop. +do { println(x); x += 1} while (x < 5) // do while loop. + +for (x <- xs if x%2 == 0) yield x*10 // for comprehension with guard +xs.filter(_%2 == 0).map(_*10) // same as filter/map +for ((x,y) <- xs zip ys) yield x*y // for comprehension: destructuring bind +(xs zip ys) map { case (x,y) => x*y } // same as +for (x <- xs; y <- ys) yield x*y // for comprehension: cross product. Later generators varying more rapidly than earlier ones +xs flatMap {x => ys map {y => x*y}} // same as for (x <- xs; y <- ys) { - println("%d/%d = %.1f".format(x, y, x/y.toFloat)) // for comprehension: imperative-ish + println("%d/%d = %.1f".format(x, y, x/y.toFloat)) // for comprehension: imperative-ish } -for (i <- 1 to 5) { // for comprehension: iterate including the upper bound +for (i <- 1 to 5) { // for comprehension: iterate including the upper bound println(i) } -for (i <- 1 until 5) { // for comprehension: iterate omitting the upper bound +for (i <- 1 until 5) { // for comprehension: iterate omitting the upper bound println(i) } -import scala.util.control.Breaks._ // break +import scala.util.control.Breaks._ // break breakable { for (x <- xs) { if (Math.random < 0.1) break @@ -223,12 +222,12 @@ Scala is a functional language in the sense that every function is a value and e Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. ```scala -def add(x: Int, y: Int): Int = x + y // the return type is declared after the parameter list and a colon +def add(x: Int, y: Int): Int = x + y // the return type is declared after the parameter list and a colon // GOOD def f(x: Any) = println(x) -// BAD def f(x) = println(x) // syntax error: need types for every arg. +// BAD def f(x) = println(x) // syntax error: need types for every arg. -def f(x: Int) = { // inferred return type +def f(x: Int) = { // inferred return type val square = x*x square.toString } // The last expression in the body is the method’s return value. (Scala does have a return keyword, but it’s rarely used.) @@ -279,10 +278,10 @@ def addColorsWithDefaults(red: Int = 0, green: Int = 0, blue: Int = 0) = { me.addColors(blue = 40) ``` -### Variable Length Arguments +### Variable Length Arguments ```scala -def sum(args: Int*) = args.reduceLeft(_+_) // varargs. must be last arg +def sum(args: Int*) = args.reduceLeft(_+_) // varargs. must be last arg def capitalizeAll(args: String*) = { args.map { arg => @@ -310,11 +309,11 @@ meaning that the last call and only call of the method is the recursive method. to a loop from a stack ```scala -import scala.annotation.tailrec // importing annotation! -@tailrec // compiler will check that the function is tail recursive +import scala.annotation.tailrec // importing annotation! +@tailrec // compiler will check that the function is tail recursive def factorial(i: BigInt): BigInt = { @tailrec - def fact(i: BigInt, accumulator: BigInt): BigInt = { // methods can be placed inside in methods; return type is obligatory + def fact(i: BigInt, accumulator: BigInt): BigInt = { // methods can be placed inside in methods; return type is obligatory if (i <= 1) accumulator else @@ -349,6 +348,7 @@ Infix Operators do NOT work if an object has a method that takes two parameters. ``` Prefix operators work if an object has a method name that starts with unary_ + ```scala class Stereo { def unary_+ = "on" @@ -382,21 +382,21 @@ val lambda3 = new Function1[Int, Int] { def apply(v1: Int): Int = v1 + 1 } -val everything = () => 42 // without parameter -val add = (x: Int, y: Int) => x + y // multiple parameters +val everything = () => 42 // without parameter +val add = (x: Int, y: Int) => x + y // multiple parameters -(1 to 5).map(_*2) // underscore notation. -(1 to 5) map (_*2) // same with infix sugar. -(1 to 5).reduceLeft( _+_ ) // underscores are positionally matched 1st and 2nd args. -(1 to 5).map( x => x*x ) // to use an arg twice, have to name it. -(1 to 5).map { x => val y = x*2; println(y); y } // block style returns last expression. +(1 to 5).map(_*2) // underscore notation. +(1 to 5) map (_*2) // same with infix sugar. +(1 to 5).reduceLeft( _+_ ) // underscores are positionally matched 1st and 2nd args. +(1 to 5).map( x => x*x ) // to use an arg twice, have to name it. +(1 to 5).map { x => val y = x*2; println(y); y } // block style returns last expression. (1 to 5) filter {_%2 == 0} map {_*2} // pipeline style (works with parens too). // GOOD (1 to 5).map(2*) -// BAD (1 to 5).map(*2) // anonymous function: bound infix method. Use 2*_ for sanity’s sake instead. +// BAD (1 to 5).map(*2) // anonymous function: bound infix method. Use 2*_ for sanity’s sake instead. def compose(g: R => R, h: R => R) = (x:R) => g(h(x)) -val f = compose({_*2}, {_-1}) // anonymous functions: to pass in multiple blocks, need outer parens. +val f = compose({_*2}, {_-1}) // anonymous functions: to pass in multiple blocks, need outer parens. ``` Passing anonymous functions as parameter: @@ -477,14 +477,14 @@ def closure = { ### Currying ```scala -val zscore = (mean: R, sd: R) => (x:R) => (x-mean)/sd // currying, obvious syntax. -def zscore(mean: R, sd: R) = (x: R) => (x-mean)/sd // currying, obvious syntax -def zscore(mean: R, sd: R)(x: R) = (x-mean)/sd // currying, sugar syntax. but then: -val normer = zscore(7, 0.4) _ // need trailing underscore to get the partial, only for the sugar version. -def mapmake[T](g: T => T)(seq: List[T]) = seq.map(g) // generic type. +val zscore = (mean: R, sd: R) => (x:R) => (x-mean)/sd // currying, obvious syntax. +def zscore(mean: R, sd: R) = (x: R) => (x-mean)/sd // currying, obvious syntax +def zscore(mean: R, sd: R)(x: R) = (x-mean)/sd // currying, sugar syntax. but then: +val normer = zscore(7, 0.4) _ // need trailing underscore to get the partial, only for the sugar version. +def mapmake[T](g: T => T)(seq: List[T]) = seq.map(g) // generic type. def multiply(x: Int, y: Int) = x * y -val multiplyCurried = (multiply _).curried +val multiplyCurried = (multiply _).curried multiply(4, 5) multiplyCurried(3)(2) ``` @@ -496,7 +496,7 @@ def adder(m: Int, n: Int) = m + n val add2 = adder(2, _:Int) // You can partially apply any argument in the argument list, not just the last one. add2(3) // which is 5 -val add3 = adder _ // underscore to convert from a function to a lambda +val add3 = adder _ // underscore to convert from a function to a lambda adder(1, 9) add3(1, 9) ``` @@ -513,10 +513,10 @@ val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { / } val tripleOdds: PartialFunction[Int, Int] = { - case x: Int if (x % 2) != 0 => x * 3 // syntaxic sugar (usual way) + case x: Int if (x % 2) != 0 => x * 3 // syntaxic sugar (usual way) } -val whatToDo = doubleEvens orElse tripleOdds // combine the partial functions together: OrElse +val whatToDo = doubleEvens orElse tripleOdds // combine the partial functions together: OrElse val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive // chain (partial) functions together: andThen @@ -525,9 +525,9 @@ val whatToDo = doubleEvens orElse tripleOdds andThen addFive // chain (partial) ## Classes, Objects, and Traits ```scala -class C(x: R) // constructor params - x is only available in class body -class C(val x: R) // c.x constructor params - automatic public (immutable) member defined -class D(var x: R) // you can define class with var or val parameters +class C(x: R) // constructor params - x is only available in class body +class C(val x: R) // c.x constructor params - automatic public (immutable) member defined +class D(var x: R) // you can define class with var or val parameters class C(var x: R) { assert(x > 0, "positive please") // constructor is class body @@ -537,36 +537,36 @@ class C(var x: R) { def this = this(42) // alternative constructor } -new{ ... } // anonymous class -abstract class D { ... } // define an abstract(non-createable) class. -class C extends D { ... } // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class -class C(x: R) extends D(x) // inheritance and constructor params. (wishlist: automatically pass-up params by default) +new{ ... } // anonymous class +abstract class D { ... } // define an abstract(non-createable) class. +class C extends D { ... } // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class +class C(x: R) extends D(x) // inheritance and constructor params. (wishlist: automatically pass-up params by default) // A class can be placed inside another class -object O extends D { ... } // define a singleton. +object O extends D { ... } // define a singleton. -trait T { ... } // traits. See below. +trait T { ... } // traits. See below. class C extends T { ... } class C extends D with T { ... } // interfaces-with-implementation. no constructor params. mixin-able. trait T1; trait T2 class C extends T1 with T2 // multiple traits. -class C extends D with T1 with T2 // parent class and (multiple) trait(s). -class C extends D { override def f = ...} // must declare method overrides. +class C extends D with T1 with T2 // parent class and (multiple) trait(s). +class C extends D { override def f = ...} // must declare method overrides. -var c = new C(4) // Instantiation +var c = new C(4) // Instantiation //BAD new List[Int] -//GOOD List(1,2,3) // Instead, convention: callable factory shadowing the type +//GOOD List(1,2,3) // Instead, convention: callable factory shadowing the type -classOf[String] // class literal. +classOf[String] // class literal. classOf[String].getCanonicalName classOf[String].getSimpleName val zoom = "zoom" zoom.getClass == classOf[String] -x.isInstanceOf[String] // type check (runtime) -x.asInstanceOf[String] // type cast (runtime) -x: String // compare to parameter ascription (compile time) +x.isInstanceOf[String] // type check (runtime) +x.asInstanceOf[String] // type cast (runtime) +x: String // compare to parameter ascription (compile time) ``` ### Methods @@ -576,7 +576,7 @@ class Complex(real: Double, imaginary: Double) { def re = real // return type inferred automatically by the compiler def im = imaginary // methods without arguments def print(): Unit = println(s"$real + i * $imaginary") - override def toString() = "" + re + (if (im < 0) "" else "+") + im + "i" // override methods inherited from a super-class + override def toString() = "" + re + (if (im < 0) "" else "+") + im + "i" // override methods inherited from a super-class } ``` @@ -617,7 +617,7 @@ Use ``A#B`` for a Java-style inner class: ```scala class Graph { class Node { - var connectedNodes: List[Graph#Node] = Nil // accepts Nodes from any Graph + var connectedNodes: List[Graph#Node] = Nil // accepts Nodes from any Graph def connectTo(node: Graph#Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes @@ -660,7 +660,7 @@ The apply method is a magical method in Scala. class Employee (val firstName:String, val lastName:String) object Employee { - def apply(firstName:String, lastName:String) = new Employee(firstName, lastName) // would also work in a class, but rarer + def apply(firstName:String, lastName:String) = new Employee(firstName, lastName) // would also work in a class, but rarer } val a = Employee("John", "Doe") @@ -680,14 +680,14 @@ var b = Employee.apply("John", "Doe") case class Person(first: String, last: String, age: Int = 0) // Case classes can have default and named parameters val p1 = Person("Fred", "Jones") // new is optional val p2 = new Person("Fred", "Jones") -p1 == p2 // true -p1.hashCode == p2.hashCode // true -p1 eq p2 // false -val p3 = p2.copy(first = "Jane") // copy the case class but change the name in the copy +p1 == p2 // true +p1.hashCode == p2.hashCode // true +p1 eq p2 // false +val p3 = p2.copy(first = "Jane") // copy the case class but change the name in the copy ``` ```scala -case class Dog(var name: String, breed: String) // Case classes can have mutable properties - potentially unsafe +case class Dog(var name: String, breed: String) // Case classes can have mutable properties - potentially unsafe ``` Case classes can be disassembled to their constituent parts as a tuple: @@ -729,25 +729,25 @@ def derive(t: Tree, v: String): Tree = t match { ```scala // GOOD (xs zip ys) map { case (x,y) => x*y } -// BAD (xs zip ys) map( (x,y) => x*y ) // use case in function args for pattern matching. +// BAD (xs zip ys) map( (x,y) => x*y ) // use case in function args for pattern matching. // BAD val v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") -} // “v42” is interpreted as a name matching any Int value, and “42” is printed. +} // “v42” is interpreted as a name matching any Int value, and “42” is printed. // GOOD val v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") -} // ”`v42`” with backticks is interpreted as the existing val v42, and “Not 42” is printed. +} // ”`v42`” with backticks is interpreted as the existing val v42, and “Not 42” is printed. // GOOD val UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") -} // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter. +} // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter. // Thus, the value contained within UppercaseVal is checked against 3, and “Not 42” is printed. ``` @@ -756,7 +756,7 @@ Some(3) match { ```scala val secondElement = List(1,2,3) match { case x :: y :: xs => xs - case x :: Nil => x + case x :: Nil => x case _ => 0 } ``` @@ -764,10 +764,10 @@ val secondElement = List(1,2,3) match { ### Regex ```scala -val MyRegularExpression = """a=([^,]+),\s+b=(.+)""".r //.r turns a String to a regular expression +val MyRegularExpression = """a=([^,]+),\s+b=(.+)""".r //.r turns a String to a regular expression expr match { case (MyRegularExpression(a, b)) => a + b - } + } ``` ```scala @@ -795,22 +795,21 @@ for (patternMatch <- keyValPattern.findAllMatchIn(input)) ```scala class Car(val make: String, val model: String, val year: Short, val topSpeed: Short) -object Car { // What is typical is to create a custom extractor in the companion object of the class. +object Car { // What is typical is to create a custom extractor in the companion object of the class. def unapply(x: Car) = Some(x.make, x.model, x.year, x.topSpeed) // returns an Option[T] } -val Car(a, b, c, d) = new Car("Chevy", "Camaro", 1978, 120) // assign values to a .. d +val Car(a, b, c, d) = new Car("Chevy", "Camaro", 1978, 120) // assign values to a .. d -val x = new Car("Chevy", "Camaro", 1978, 120) match { // pattern matching - case Car(s, t, _, _) => (s, t) // _ for variables we don't care about. - case _ => ("Ford", "Edsel") // fallback +val x = new Car("Chevy", "Camaro", 1978, 120) match { // pattern matching + case Car(s, t, _, _) => (s, t) // _ for variables we don't care about. + case _ => ("Ford", "Edsel") // fallback } ``` - As long as the method signatures aren't the same, you can have an many unapply methods as you want in the same class / object. - When you create a case class, it automatically can be used with pattern matching since it has an extractor. - ### Value Class Avoid allocating runtime objects. @@ -820,6 +819,7 @@ class Wrapper(val underlying: Int) extends AnyVal { def foo: Wrapper = new Wrapper(underlying * 19) } ``` + It has a single, public val parameter that is the underlying runtime representation. The type at compile time is Wrapper, but at runtime, the representation is an Int. A value class can define defs, but no vals, vars, or nested traitss, classes or objects A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation. @@ -898,7 +898,7 @@ trait Doubling extends IntQueue { abstract override def put(x: Int) { super.put(2 * x) } // abstract override is necessary to stack traits } -class MyQueue extends BasicIntQueue with Doubling // could also mixin during instantiation +class MyQueue extends BasicIntQueue with Doubling // could also mixin during instantiation val myQueue = new MyQueue myQueue.put(3) @@ -922,9 +922,9 @@ Use traits: - When a behavior is going to be reused in multiple unrelated classes. - When you want to define interfaces and want to use them outside Scala, for example Java. The reason is that the traits that do not have any implementations are compiled similar to interfaces. - ## Keyword List +```txt abstract case catch @@ -973,4 +973,5 @@ Use traits: <% >: # - @ \ No newline at end of file + @ +``` diff --git a/docs/Scala/Scala_Language/index.html b/docs/Scala/Scala_Language/index.html deleted file mode 100644 index 9dc7e53..0000000 --- a/docs/Scala/Scala_Language/index.html +++ /dev/null @@ -1,3445 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Language - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Scala Language

- - - -

Some examples are derived from Scala Koans.

-

Basics

-

Style

-

Class Names - For all class names, the first letter should be in Upper Case. If several words are used to form a name of the class, each inner word's first letter should be in Upper Case.

-

class MyFirstScalaClass

-

Method Names - All method names should start with a Lower Case letter. If multiple words are used to form the name of the method, then each inner word's first letter should be in Upper Case.

-

def myMethodName()

-

Program File Name - Name of the program file should exactly match the object name. When saving the file you should save it using the object name (Remember Scala is case-sensitive) and append ".scala" to the end of the name. If the file name and the object name do not match your program will not compile.

-

Assume 'HelloWorld' is the object name: the file should be saved as 'HelloWorld.scala'.

-

Packages

-
package pkg         // at start of file
-package pkg { ... } // bracket style
-
- -

Imports

-
import scala.collection._                   // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*).
-import scala.collection.Vector              // one class import
-import scala.collection.{Vector, Sequence}  // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces
-import scala.collection.{Vector => Vec28}   // renaming import.
-import java.util.{Date => _, _}             // import all from java.util except Date.
-
- -

All classes from the java.lang package are imported by default. The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification: -- immutable Map, Set, List, ::, Nil, print, println, assert, assume, require, ensuring

-
import scala.collection.mutable.HashMap               // Mutable collections must be imported.
-import scala.collection.immutable.{TreeMap, TreeSet}  // So are specialized collections.
-
- -

Application Entry Point

-
object HelloWorld {
-    def main(args: Array[String]) {
-        println("Hello, world!")
-    }
-}
-
- -

Blocks

-

You can combine expressions by surrounding them with {}. We call this a block. -The result of the last expression in the block is the result of the overall block, too.

-
println({
-  val x = 1 + 1
-  x + 1
-}) // 3
-
- -

Variables and Values

-
var x = 5 // variable
-val x = 5 // immutable value / "const"
-var x: Double = 5 // explicit type
-println(x)
-
- -

A lazy val is assignment that will not evaluated until it is called. Note there is no lazy var

-
lazy val a = {heavymath(); 19}
-
- -

Literals

-
val a = 2       // int
-val b = 31L     // long
-val c = 0x30B   // hexadecimal
-val d = 3f      // float
-val e = 3.22d   // double
-val f = 93e-9
-val g = 'a'         // character
-val h = '\u0061'    // unicode for a
-val i = '\141'      // octal for a
-val j = '\"'        // escape sequences
-val k = '\\'
-val s = "To be or not to be"    // string
-s.charAt(0)
-val s2 = """An apple a day
-keeps the doctor away"""        // multi-lines string
-s2.split('\n')
-val s3 = """An apple a day
-           |keeps the doctor away"""  // Multiline String literals can use | to specify the starting position of subsequent lines, then use stripMargin to remove the surplus indentation.
-s3.stripMargin
-
- -

Enumerations

-
object Planets extends Enumeration {
-  val Mercury = Value
-  val Venus = Value
-  val Earth = Value
-  val Mars = Value
-  val Jupiter = Value
-  val Saturn = Value
-  val Uranus = Value
-  val Neptune = Value
-  val Pluto = Value
-}
-
-Planets.Mercury.id
-Planets.Mercury.toString //How does it get the name? by Reflection.
-
-object GreekPlanets extends Enumeration {
-  val Mercury = Value(1, "Hermes")   // enumeration with your own index and/or your own Strings
-  val Venus = Value(2, "Aphrodite")
-  //Fun Fact: Tellus is Roman for (Mother) Earth
-  val Earth = Value(3, "Gaia")
-  val Mars = Value(4, "Ares")
-  val Jupiter = Value(5, "Zeus")
-  val Saturn = Value(6, "Cronus")
-  val Uranus = Value(7, "Ouranus")
-  val Neptune = Value(8, "Poseidon")
-  val Pluto = Value(9, "Hades")
-}
-
- -

Common Data Structures

-
(1,2,3)                     // tuple literal. (Tuple3)
-var (x,y,z) = (1,2,3)       // destructuring bind: tuple unpacking via pattern matching.
-// BAD var x,y,z = (1,2,3)  // hidden error: each assigned to the entire tuple.
-
-val tuple = ("apple", 3)    // mixed type tuple
-tuple._1
-tuple._2
-tuple.swap
-
- -
var xs = List(1,2,3)        // list (immutable).
-xs(2)                       // paren indexing
-1 :: List(2,3)              // cons (create a new list by prepending the element).
-
-1 to 5                      // Range sugar. Same as `1 until 6`
-1 to 10 by 2
-Range(1, 10, 2)             // Range does not include the last item, even in a step increment
-Range(1, 9, 2).inclusive
-
- -
()                          // (empty parens)   sole member of the Unit type (like C/Java void).
-
- -

Control Constructs

-
if (check) happy else sad   // conditional.
-if (check) happy            //
-if (check) happy else ()    // same as above
-while (x < 5) { println(x); x += 1} // while loop.
-do { println(x); x += 1} while (x < 5)  // do while loop.
-
-for (x <- xs if x%2 == 0) yield x*10    // for comprehension with guard
-xs.filter(_%2 == 0).map(_*10)           // same as filter/map
-for ((x,y) <- xs zip ys) yield x*y      // for comprehension: destructuring bind
-(xs zip ys) map { case (x,y) => x*y }   // same as
-for (x <- xs; y <- ys) yield x*y        // for comprehension: cross product. Later generators varying more rapidly than earlier ones
-xs flatMap {x => ys map {y => x*y}}     // same as
-for (x <- xs; y <- ys) {
-  println("%d/%d = %.1f".format(x, y, x/y.toFloat))     // for comprehension: imperative-ish
-}
-for (i <- 1 to 5) {                     // for comprehension: iterate including the upper bound
-  println(i)
-}
-for (i <- 1 until 5) {                  // for comprehension: iterate omitting the upper bound
-  println(i)
-}
-
-import scala.util.control.Breaks._      // break
-breakable {
-  for (x <- xs) {
-    if (Math.random < 0.1) break
-  }
-}
-
- -

Formatting and Interpolation

-
val helloMessage = "Hello World"
-s"Application $helloMessage"  // string interpolation; can include expressions which can include numbers and strings
-// use `f` prefix before the string instead of an `s` for sprintf formatting
-
- -

Functions

-

Scala is a functional language in the sense that every function is a value and every value is an object so ultimately every function is an object. -Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying.

-
def add(x: Int, y: Int): Int = x + y    // the return type is declared after the parameter list and a colon
-
-// GOOD def f(x: Any) = println(x)
-// BAD  def f(x) = println(x)           // syntax error: need types for every arg.
-
-def f(x: Int) = {                       // inferred return type
-  val square = x*x
-  square.toString
-  } // The last expression in the body is the method’s return value. (Scala does have a return keyword, but it’s rarely used.)
-
-// BAD def f(x: Int) { x*x }  hidden error: without = it’s a Unit-returning procedure; causes havoc
-
-// When performing recursion, the return type on the method is mandatory!
-
- -
    -
  • Backticks for reserved keywords and identifiers with a space (rare)
  • -
-
def `put employee on probation`(employee: Employee) = {
-       new Employee(employee.`first name`, employee.`last name`, "Probation")
-    }
-
- -

Multiple parameter lists or none at all

-
def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
-def name: String = System.getProperty("name")
-
- -

Procedures

-
def foo(x: Int) { //Note: No `=`; returns Unit
-      print(x.toString)
-    }
-def foo(x: Int): Unit =  print(x.toString)  // or
-
- -

Convention (not required for the compiler) states that if you a call a method that returns a Unit / has a side effect, invoke that method with empty parenthesis, other leave the parenthesis out

-
def performSideEffect():Unit = System.currentTimeMillis
-performSideEffect()
-
- -

Default and named parameters

-
def addColorsWithDefaults(red: Int = 0, green: Int = 0, blue: Int = 0) = {
-  (red, green, blue)
-}
-
-me.addColors(blue = 40)
-
- -

Variable Length Arguments

-
def sum(args: Int*) = args.reduceLeft(_+_)              // varargs. must be last arg
-
-def capitalizeAll(args: String*) = {
-      args.map { arg =>
-        arg.capitalize
-      }
-    }
-
-capitalizeAll("rarity", "applejack")
-
- -

If you want a collection expanded into a vararg, add :_*

-
def repeatedParameterMethod(x: Int, y: String, z: Any*) = {
-    "%d %ss can give you %s".format(x, y, z.mkString(", "))
-  }
-
-repeatedParameterMethod(3, "egg", List("a delicious sandwich", "protein", "high cholesterol"):_*) should be(__)
-
- -

Tail recursion

-

As a precaution, the helpful @tailrec annotation will throw a compile time if a method is not tail recursive, -meaning that the last call and only call of the method is the recursive method. Scala optimizes recursive calls -to a loop from a stack

-
import scala.annotation.tailrec //  importing annotation!
-@tailrec                        //  compiler will check that the function is tail recursive
-def factorial(i: BigInt): BigInt = {
-      @tailrec
-      def fact(i: BigInt, accumulator: BigInt): BigInt = {  // methods can be placed inside in methods; return type is obligatory
-        if (i <= 1)
-          accumulator
-        else
-          fact(i - 1, i * accumulator)
-      }
-      fact(i, 1)
-    }
-
-factorial(3)
-
- -

Infix, Postfix and Prefix Notations; Operators

-
object FrenchDate {
-    def main(args: Array[String]) {
-        val now = new Date
-        val df = getDateInstance(LONG, Locale.FRANCE)
-    println(df format now)       // Methods taking one argument can be used with an infix syntax. Equivalent to df.format(now)
-    }
-}
-
- -

1 + 2 * 3 / x consists exclusively of method calls, because it is equivalent to the following expression: (1).+(((2).*(3))./(x)) -This also means that +, *, etc. are valid identifiers in Scala.

-

Infix Operators do NOT work if an object has a method that takes two parameters.

-
 val g: Int = 31
- val s: String = g toHexString  // Postfix operators work if an object has a method that takes no parameters
-
- -

Prefix operators work if an object has a method name that starts with unary_

-
class Stereo {
-      def unary_+ = "on"
-      def unary_- = "off"
-    }
-
-val stereo = new Stereo
-+stereo   // it is on
-
- -

Methods with colons are right-associative, that means the object that a method is on will be on the right and the method parameter will be on the left

-
class Foo (y:Int) {
-      def ~:(n:Int) = n + y + 3
-    }
-
-val foo = new Foo(9)
-10 ~: foo
-foo.~:(10)  // same as
-
- -

Anonymous Functions

-
def lambda = (x: Int) => x + 1
-
-// other variants
-def lambda2 = { x: Int => x + 1 }
-val lambda3 = new Function1[Int, Int] {
-      def apply(v1: Int): Int = v1 + 1
-    }
-
-val everything = () => 42                       // without parameter
-val add = (x: Int, y: Int) => x + y             // multiple parameters
-
-(1 to 5).map(_*2)                               // underscore notation.
-(1 to 5) map (_*2)                              // same with infix sugar.
-(1 to 5).reduceLeft( _+_ )                      // underscores are positionally matched 1st and 2nd args.
-(1 to 5).map( x => x*x )                        // to use an arg twice, have to name it.
-(1 to 5).map { x => val y = x*2; println(y); y }    // block style returns last expression.
-(1 to 5) filter {_%2 == 0} map {_*2}            // pipeline style (works with parens too).
-
-// GOOD (1 to 5).map(2*)
-// BAD (1 to 5).map(*2)                         // anonymous function: bound infix method. Use 2*_ for sanity’s sake instead.
-
-def compose(g: R => R, h: R => R) = (x:R) => g(h(x))
-val f = compose({_*2}, {_-1})                   // anonymous functions: to pass in multiple blocks, need outer parens.
-
- -

Passing anonymous functions as parameter:

-
def makeWhatEverYouLike(xs: List[String], func: String => String) = {
-      xs map func
-    }
-
- -

Function returning another function using an anonymous function:

-
def add(x: Int) = (y:Int) => x + y
-
- -

Function Values:

-
object Timer {
-    def oncePerSecond(callback: () => Unit) {        // () => T is a Function type that takes a Unit type. Unit is known as 'void' to a Java programmer.
-        while (true) { callback(); Thread sleep 1000 }
-    }
-
-    def timeFlies() {
-        println("time flies like an arrow...")
-    }
-
-    def main(args: Array[String]) {
-        oncePerSecond(timeFlies)       // function value; could also be () => timeFlies()
-    }
-}
-
- -

By-name parameter

-

This is used extensively in scala to create blocks.

-
    def calc(x: => Int): Either[Throwable, Int] = {   //x is a call by name parameter; delayed execution of x
-      try {
-        Right(x)
-      } catch {
-        case b: Throwable => Left(b)
-      }
-    }
-
-    val y = calc {                                    //This looks like a natural block
-      println("Here we go!")                          //Some superfluous call
-      49 + 20
-    }
-
- -

By name parameters can also be used with an Object and apply to make interesting block-like calls

-
object PigLatinizer {
-      def apply(x: => String) = x.tail + x.head + "ay"
-    }
-
-val result = PigLatinizer {
-      val x = "pret"
-      val z = "zel"
-      x ++ z //concatenate the strings
-    }
-
- -

Closures

-
var incrementer = 1
-
-def closure = {
-  x: Int => x + incrementer
-}
-
- -

Currying

-
val zscore = (mean: R, sd: R) => (x:R) => (x-mean)/sd       // currying, obvious syntax.
-def zscore(mean: R, sd: R) = (x: R) => (x-mean)/sd          // currying, obvious syntax
-def zscore(mean: R, sd: R)(x: R) = (x-mean)/sd              // currying, sugar syntax. but then:
-val normer = zscore(7, 0.4) _                               // need trailing underscore to get the partial, only for the sugar version.
-def mapmake[T](g: T => T)(seq: List[T]) = seq.map(g)        // generic type.
-
-def multiply(x: Int, y: Int) = x * y
-val multiplyCurried = (multiply _).curried                  
-multiply(4, 5)
-multiplyCurried(3)(2)
-
- -

Partial Applications

-
def adder(m: Int, n: Int) = m + n
-val add2 = adder(2, _:Int)  // You can partially apply any argument in the argument list, not just the last one.
-add2(3)    // which is 5
-
-val add3 = adder _              // underscore to convert from a function to a lambda
-adder(1, 9)
-add3(1, 9)
-
- -

Partial Functions

-
val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] {   // full declaration
-      //States that this partial function will take on the task
-      def isDefinedAt(x: Int) = x % 2 == 0
-
-      //What we do if this does partial function matches
-      def apply(v1: Int) = v1 * 2
-    }
-
-val tripleOdds: PartialFunction[Int, Int] = {
-      case x: Int if (x % 2) != 0 => x * 3              // syntaxic sugar (usual way)
-    }
-
-val whatToDo = doubleEvens orElse tripleOdds            //  combine the partial functions together: OrElse
-
-val addFive = (x: Int) => x + 5
-val whatToDo = doubleEvens orElse tripleOdds andThen addFive  // chain (partial) functions together: andThen
-
- -

Classes, Objects, and Traits

-
class C(x: R)                       // constructor params - x is only available in class body
-class C(val x: R)                   // c.x  constructor params - automatic public (immutable) member defined
-class D(var x: R)                   // you can define class with var or val parameters
-
-class C(var x: R) {
-  assert(x > 0, "positive please")  // constructor is class body
-  var y = x                         // declare a public member
-  val readonly = 5                  // declare a gettable but not settable member
-  private var secret = 1            // declare a private member
-  def this = this(42)               // alternative constructor
-}
-
-new{ ... }  // anonymous class
-abstract class D { ... }    // define an abstract(non-createable) class.
-class C extends D { ... }   // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class
-class C(x: R) extends D(x)  // inheritance and constructor params. (wishlist: automatically pass-up params by default)
-// A class can be placed inside another class
-object O extends D { ... }  // define a singleton.
-
-trait T { ... }             // traits. See below.
-class C extends T { ... }
-class C extends D with T { ... }
-
-// interfaces-with-implementation. no constructor params. mixin-able.
-trait T1; trait T2
-class C extends T1 with T2          // multiple traits.
-class C extends D with T1 with T2   // parent class and (multiple) trait(s).
-class C extends D { override def f = ...}   // must declare method overrides.
-
-var c = new C(4)        // Instantiation
-//BAD new List[Int]
-//GOOD List(1,2,3)      // Instead, convention: callable factory shadowing the type
-
-classOf[String] // class literal.
-classOf[String].getCanonicalName
-classOf[String].getSimpleName
-val zoom = "zoom"
-zoom.getClass == classOf[String]
-
-x.isInstanceOf[String]  // type check (runtime)
-x.asInstanceOf[String]  // type cast (runtime)
-x: String               // compare to parameter ascription (compile time)
-
- -

Methods

-
class Complex(real: Double, imaginary: Double) {
-    def re = real       // return type inferred automatically by the compiler
-    def im = imaginary  // methods without arguments
-    def print(): Unit = println(s"$real + i * $imaginary")
-    override def toString() = "" + re + (if (im < 0) "" else "+") + im + "i"  // override methods inherited from a super-class
-}
-
- -

Asserts and Contracts

-

Asserts take a boolean argument and can take a message.

-
assert(true) // should be true
-assert(true, "This should be true")
-
- -
def addNaturals(nats: List[Int]): Int = {
-  require(nats forall (_ >= 0), "List contains negative numbers")
-  nats.foldLeft(0)(_ + _)
-} ensuring(_ >= 0)
-
- -

Path-dependent Classes

-

When a class is instantiated inside of another object, it belongs to the instance. This is a path dependent type. Once established, it cannot be placed inside of another object

-
case class Board(length: Int, height: Int) {
-  case class Coordinate(x: Int, y: Int)
-}
-
-val b1 = Board(20, 20)
-val b2 = Board(30, 30)
-val c1 = b1.Coordinate(15, 15)
-val c2 = b2.Coordinate(25, 25)
-// val c1 = c2  won't work
-
- -

Use A#B for a Java-style inner class:

-
class Graph {
-  class Node {
-    var connectedNodes: List[Graph#Node] = Nil          // accepts Nodes from any Graph
-    def connectTo(node: Graph#Node) {
-      if (connectedNodes.find(node.equals).isEmpty) {
-        connectedNodes = node :: connectedNodes
-      }
-    }
-  }
-  var nodes: List[Node] = Nil
-  def newNode: Node = {
-    val res = new Node
-    nodes = res :: nodes
-    res
-  }
-}
-
- -

Companion Objects

-

Static members (methods or fields) do not exist in Scala. Rather than defining static members, the Scala programmer declares these members in singleton objects, that is a class with a single instance.

-
object TimerAnonymous {
-    def oncePerSecond(callback: () => Unit) {
-        while (true) { callback(); Thread sleep 1000 }
-    }
-    def main(args: Array[String]) {
-        oncePerSecond(() => println("time flies like an arrow..."))
-    }
-}
-
- -
    -
  • An object that has the same name as class is called a companion object, it is used to contain factories for the class that it complements.
  • -
  • A companion object can also store shared variables and values for every instantiated class to share.
  • -
  • A companion object can see private values and variables of the instantiated object
  • -
-

Apply Method

-

The apply method is a magical method in Scala.

-
class Employee (val firstName:String, val lastName:String)
-
-object Employee {
-    def apply(firstName:String, lastName:String) = new Employee(firstName, lastName)  // would also work in a class, but rarer
-}
-
-val a = Employee("John", "Doe")
-// is equivalent to
-var b = Employee.apply("John", "Doe")
-
- -

Case Classes

-
    -
  • The new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)),
  • -
  • Getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v),
  • -
  • Default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity,
  • -
  • A default definition for method toString is provided, and prints the value in a source form (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))),
  • -
  • Instances of these classes can be decomposed through pattern matching
  • -
-
case class Person(first: String, last: String, age: Int = 0)  // Case classes can have default and named parameters
-val p1 = Person("Fred", "Jones")    // new is optional
-val p2 = new Person("Fred", "Jones")
-p1 == p2                            // true
-p1.hashCode == p2.hashCode          // true
-p1 eq p2                            // false
-val p3 = p2.copy(first = "Jane")    // copy the case class but change the name in the copy
-
- -
case class Dog(var name: String, breed: String)     // Case classes can have mutable properties - potentially unsafe
-
- -

Case classes can be disassembled to their constituent parts as a tuple:

-
val parts = Person.unapply(p1).get // returns Option[T]
-parts._1
-parts._2
-
- -

Algebraic data type

-
sealed trait Tree    // or abstract class
-final case class Sum(l: Tree, r: Tree) extends Tree
-final case class Var(n: String) extends Tree
-final case class Const(v: Int) extends Tree
-
- -

Pattern Matching

-

{ case "x" => 5 } defines a partial function which, when given the string "x" as argument, returns the integer 5, and fails with an exception otherwise.

-
type Environment = String => Int  // the type Environment can be used as an alias of the type of functions from String to Int
-
-def eval(t: Tree, env: Environment): Int = t match {
-    case Sum(l, r) => eval(l, env) + eval(r, env)
-    case Var(n) => env(n)
-    case Const(v) => v
-}
-
-def derive(t: Tree, v: String): Tree = t match {
-    case Sum(l, r) => Sum(derive(l, v), derive(r, v))
-    case Var(n) if (v == n) => Const(1)                  // guard, an expression following the if keyword.
-    case _ => Const(0)                                   // wild-card, written _, which is a pattern matching any value, without giving it a name.
-}
-
- -
// GOOD (xs zip ys) map { case (x,y) => x*y }
-// BAD (xs zip ys) map( (x,y) => x*y )  // use case in function args for pattern matching.
-// BAD
-val v42 = 42
-Some(3) match {
-  case Some(v42) => println("42")
-  case _ => println("Not 42")
-}   // “v42” is interpreted as a name matching any Int value, and “42” is printed.
-// GOOD
-val v42 = 42
-Some(3) match {
-  case Some(`v42`) => println("42")
-  case _ => println("Not 42")
-}   // ”`v42`” with backticks is interpreted as the existing val v42, and “Not 42” is printed.
-// GOOD
-val UppercaseVal = 42
-Some(3) match {
-  case Some(UppercaseVal) => println("42")
-  case _ => println("Not 42")
-}   // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter.
-// Thus, the value contained within UppercaseVal is checked against 3, and “Not 42” is printed.
-
- -

List Matching

-
val secondElement = List(1,2,3) match {
-      case x :: y :: xs => xs
-      case x :: Nil => x
-      case _ => 0
-    }
-
- -

Regex

-
val MyRegularExpression = """a=([^,]+),\s+b=(.+)""".r           //.r turns a String to a regular expression
-expr match {
-      case (MyRegularExpression(a, b)) => a + b
-      }
-
- -
import scala.util.matching.Regex
-
-val numberPattern: Regex = "[0-9]".r
-
-numberPattern.findFirstMatchIn("awesomepassword") match {
-  case Some(_) => println("Password OK")
-  case None => println("Password must contain a number")
-}
-
- -

With groups:

-
val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r
-
-for (patternMatch <- keyValPattern.findAllMatchIn(input))
-  println(s"key: ${patternMatch.group(1)} value: ${patternMatch.group(2)}")
-
- -

Extractors (unapply)

-
class Car(val make: String, val model: String, val year: Short, val topSpeed: Short)
-
-object Car {                                                        // What is typical is to create a custom extractor in the companion object of the class.
-  def unapply(x: Car) = Some(x.make, x.model, x.year, x.topSpeed)   // returns an Option[T]
-}
-
-val Car(a, b, c, d) = new Car("Chevy", "Camaro", 1978, 120)     // assign values to a .. d
-
-val x = new Car("Chevy", "Camaro", 1978, 120) match {           // pattern matching
-  case Car(s, t, _, _) => (s, t)                                // _ for variables we don't care about.
-  case _ => ("Ford", "Edsel")                                   // fallback
-}
-
- -
    -
  • As long as the method signatures aren't the same, you can have an many unapply methods as you want in the same class / object.
  • -
  • When you create a case class, it automatically can be used with pattern matching since it has an extractor.
  • -
-

Value Class

-

Avoid allocating runtime objects.

-
class Wrapper(val underlying: Int) extends AnyVal {
-  def foo: Wrapper = new Wrapper(underlying * 19)
-}
-
- -

It has a single, public val parameter that is the underlying runtime representation. The type at compile time is Wrapper, but at runtime, the representation is an Int. A value class can define defs, but no vals, vars, or nested traitss, classes or objects

-

A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation.

-

Traits

-

Apart from inheriting code from a super-class, a Scala class can also import code from one or several traits i.e. interfaces which can also contain code. -In Scala, when a class inherits from a trait, it implements that traits's interface, and inherits all the code contained in the trait.

-
trait Ord {
-    def < (that: Any): Boolean                              // The type Any which is used above is the type which is a super-type of all other types in Scala
-    def <=(that: Any): Boolean = (this < that) || (this == that)
-    def > (that: Any): Boolean = !(this <= that)
-    def >=(that: Any): Boolean = !(this < that)
-}
-
-class Date(y: Int, m: Int, d: Int) extends Ord {
-    def year = y
-    def month = m
-    def day = d
-    override def toString(): String = year + "-" + month + "-" + day
-
-    override def equals(that: Any): Boolean =
-        that.isInstanceOf[Date] && {
-        val o = that.asInstanceOf[Date]
-        o.day == day && o.month == month && o.year == year
-    }
-
-    def <(that: Any): Boolean = {    // The trait declare the type (e.g. method), where a concrete implementer will satisfy the type
-        if (!that.isInstanceOf[Date])
-            error("cannot compare " + that + " and a Date")
-        val o = that.asInstanceOf[Date](year < o.year) ||
-            (year == o.year && (month < o.month ||
-            (month == o.month && day < o.day    )))
-    }
-}
-
- -
    -
  • -

    Traits can have concrete implementations that can be mixed into concrete classes with its own state

    -
  • -
  • -

    Traits can be mixed in during instantiation!

    -
  • -
-
trait Logging {
-      var logCache = List[String]()
-
-      def log(value: String) = {
-        logCache = logCache :+ value
-      }
-
-      def log = logCache
-    }
-val a = new A("stuff") with Logging  // mixin traits during instantiation!
-a.log("I did something")
-a.log.size
-
- -

Stackable Traits

-
abstract class IntQueue {
-  def get(): Int
-  def put(x: Int)
-}
-
-import scala.collection.mutable.ArrayBuffer
-
-class BasicIntQueue extends IntQueue {
-  private val buf = new ArrayBuffer[Int]
-  def get() = buf.remove(0)
-  def put(x: Int) { buf += x }
-}
-
-trait Doubling extends IntQueue {
-  abstract override def put(x: Int) { super.put(2 * x) }    // abstract override is necessary to stack traits
-}
-
-class MyQueue extends BasicIntQueue with Doubling           // could also mixin during instantiation
-
-val myQueue = new MyQueue
-myQueue.put(3)
-myQueue.get()
-
- -
    -
  • More traits can be stacked one atop another, make sure that all overrides are labelled abstract override.
  • -
  • The order of the mixins are important. Traits on the right take effect first.
  • -
  • Traits are instantiated before a classes instantiation from left to right.
  • -
  • Linerization: the diamond inheritance problem is avoided since instantiations are tracked and will not allow multiple instantiations of the same parent trait
  • -
-

Classes versus Traits

-

Use classes:

-
    -
  • When a behavior is not going to be reused at all or in multiple places
  • -
  • When you plan to use your Scala code from another language, for example, if you are building a library that could be used in Java
  • -
-

Use traits:

-
    -
  • When a behavior is going to be reused in multiple unrelated classes.
  • -
  • When you want to define interfaces and want to use them outside Scala, for example Java. The reason is that the traits that do not have any implementations are compiled similar to interfaces.
  • -
-

Keyword List

-
abstract
-case
-catch
-class
-def
-do
-else
-extends
-false
-final
-finally
-for
-forSome
-if
-implicit
-import
-lazy
-match
-new
-Null
-object
-override
-package
-private
-protected
-return
-sealed
-super
-this
-throw
-trait
-Try
-true
-type
-val
-var
-while
-with
-yield
- -
- :
- =
- =>
-<-
-<:
-<%
->:
-#
-@
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Testing.md b/docs/Scala/Scala_Testing.md similarity index 64% rename from docs_src/Scala/Scala_Testing.md rename to docs/Scala/Scala_Testing.md index e6c7cff..6b40643 100644 --- a/docs_src/Scala/Scala_Testing.md +++ b/docs/Scala/Scala_Testing.md @@ -6,12 +6,11 @@ tags: Scala, Tests ## Links -[http://www.scalatest.org/](http://www.scalatest.org/) +[https://www.scalatest.org/](https://www.scalatest.org/) [Writing TDD unit tests with scalatest](https://alvinalexander.com/scala/writing-tdd-unit-tests-with-scalatest) -[At a Glance](http://www.scalatest.org/at_a_glance/) - +[At a Glance](https://www.scalatest.org/at_a_glance/) ## Examples @@ -26,7 +25,7 @@ import org.scalatest.FunSuite import org.scalatest.BeforeAndAfter class PizzaTests extends FunSuite with BeforeAndAfter { - + var pizza: Pizza = _ before { @@ -48,29 +47,29 @@ class PizzaTests extends FunSuite with BeforeAndAfter { } ``` -## [Styles](http://www.scalatest.org/at_a_glance/) +## [Styles](https://www.scalatest.org/at_a_glance/) ### FunSuite ```scala -import org.scalatest.FunSuite -class AddSuite extends FunSuite { - test("3 plus 3 is 6") { - assert((3 + 3) == 6) - } +import org.scalatest.FunSuite +class AddSuite extends FunSuite { + test("3 plus 3 is 6") { + assert((3 + 3) == 6) + } } ``` ### FlatSpec The structure of this test is flat—like xUnit, but the test name can be written in specification style: - + ```scala -import org.scalatest.FlatSpec -class AddSpec extends FlatSpec { - "Addition of 3 and 3" should "have result 6" in { - assert((3 + 3) == 0) - } +import org.scalatest.FlatSpec +class AddSpec extends FlatSpec { + "Addition of 3 and 3" should "have result 6" in { + assert((3 + 3) == 0) + } } ``` @@ -92,33 +91,33 @@ class ExampleSpec extends FlatSpec with Matchers { val emptyStack = new Stack[Int] a [NoSuchElementException] should be thrownBy { emptyStack.pop() - } + } } } -``` +``` ### FeatureSpec ```scala -import org.scalatest._ +import org.scalatest._ + +class Calculator { + def add(a:Int, b:Int): Int = a + b +} -class Calculator { - def add(a:Int, b:Int): Int = a + b -} - class CalcSpec extends FeatureSpec with GivenWhenThen { - info("As a calculator owner") - info("I want to be able add two numbers") - info("so I can get a correct result") + info("As a calculator owner") + info("I want to be able add two numbers") + info("so I can get a correct result") feature("Addition") { scenario("User adds two numbers") { - Given("a calculator") - val calc = new Calculator - When("two numbers are added") - var result = calc.add(3, 3) - Then("we get correct result") - assert(result == 6) + Given("a calculator") + val calc = new Calculator + When("two numbers are added") + var result = calc.add(3, 3) + Then("we get correct result") + assert(result == 6) } - } -} + } +} ``` diff --git a/docs/Scala/Scala_Testing/index.html b/docs/Scala/Scala_Testing/index.html deleted file mode 100644 index 6c17508..0000000 --- a/docs/Scala/Scala_Testing/index.html +++ /dev/null @@ -1,2139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Testing - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Scala Testing

- - -

http://www.scalatest.org/

-

Writing TDD unit tests with scalatest

-

At a Glance

-

Examples

-
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" % "test"
-
- -
package com.acme.pizza
-
-import org.scalatest.FunSuite
-import org.scalatest.BeforeAndAfter
-
-class PizzaTests extends FunSuite with BeforeAndAfter {
-
-  var pizza: Pizza = _
-
-  before {
-    pizza = new Pizza
-  }
-
-  test("new pizza has zero toppings") {
-    assert(pizza.getToppings.size == 0)
-  }
-
-  test("adding one topping") {
-    pizza.addTopping(Topping("green olives"))
-    assert(pizza.getToppings.size === 1)
-  }
-
-  // mark that you want a test here in the future
-  test ("test pizza pricing") (pending)
-
-}
-
- -

Styles

-

FunSuite

-
import org.scalatest.FunSuite 
-class AddSuite extends FunSuite {    
-  test("3 plus 3 is 6") {      
-     assert((3 + 3) == 6)    
-  }  
-}
-
- -

FlatSpec

-

The structure of this test is flat—like xUnit, but the test name can be written in specification style:

-
import org.scalatest.FlatSpec  
-class AddSpec extends FlatSpec {  
-  "Addition of 3 and 3" should "have result 6" in { 
-    assert((3 + 3) == 0)    
-  }  
-}
-
- -
import collection.mutable.Stack
-import org.scalatest._
-
-class ExampleSpec extends FlatSpec with Matchers {
-
-  "A Stack" should "pop values in last-in-first-out order" in {
-    val stack = new Stack[Int]
-    stack.push(1)
-    stack.push(2)
-    stack.pop() should be (2)
-    stack.pop() should be (1)
-  }
-
-  it should "throw NoSuchElementException if an empty stack is popped" in {
-    val emptyStack = new Stack[Int]
-    a [NoSuchElementException] should be thrownBy {
-      emptyStack.pop()
-    } 
-  }
-}
-
- -

FeatureSpec

-
import org.scalatest._  
-
-class Calculator {    
-  def add(a:Int, b:Int): Int = a + b 
-} 
-
-class CalcSpec extends FeatureSpec with GivenWhenThen {
-  info("As a calculator owner")    
-  info("I want to be able add two numbers")    
-  info("so I can get a correct result")    
-  feature("Addition") {
-    scenario("User adds two numbers") {
-      Given("a calculator")        
-      val calc = new Calculator 
-      When("two numbers are added")        
-      var result = calc.add(3, 3) 
-      Then("we get correct result")        
-       assert(result == 6)      
-    }
-  }  
-} 
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scala_Types.md b/docs/Scala/Scala_Types.md similarity index 96% rename from docs_src/Scala/Scala_Types.md rename to docs/Scala/Scala_Types.md index 1725c7e..7c0e157 100644 --- a/docs_src/Scala/Scala_Types.md +++ b/docs/Scala/Scala_Types.md @@ -18,14 +18,13 @@ trait Persister { } // our refined instance (and type): -val refinedMockPersister = new Persister { - override def doPersist(e: Entity) = () +val refinedMockPersister = new Persister { + override def doPersist(e: Entity) = () } ``` [Scala Types of Types](https://ktoso.github.io/scala-types-of-types/#refined-types-refinements) - ## Generics ```scala @@ -81,7 +80,6 @@ class PetContainer[P <: Pet](p: P) { Lower type bounds declare a type to be a supertype of another type. The term ``B >: A`` expresses that the type parameter B or the abstract type B refer to a supertype of type A. - ## Abstract Types ```scala @@ -181,7 +179,7 @@ trait Wrong extends Tweeter { If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error. -* Self types allow you to define cyclical dependencies. For example, you can achieve this: +- Self types allow you to define cyclical dependencies. For example, you can achieve this: ```scala trait A { self: B => } @@ -190,7 +188,7 @@ trait B { self: A => } Inheritance using extends does not allow that. -* Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as: +- Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as: ```scala sealed trait Person @@ -209,13 +207,12 @@ p match { Implicits wrap around existing classes to provide extra functionality - ```scala object MyPredef { // usually in a companion object class IntWrapper(val original: Int) { - def isOdd = original % 2 != 0 - def isEven = !isOdd + def isOdd = original % 2 != 0 + def isEven = !isOdd } implicit def thisMethodNameIsIrrelevant(value: Int) = new IntWrapper(value) @@ -257,5 +254,3 @@ def inspect[T](l: List[T])(implicit tt: TypeTag[T]) = tt.tpe.typeSymbol.name.dec ``` TypeTags can be used to determine a type used before it erased by the VM by using an implicit TypeTag argument. - - diff --git a/docs/Scala/Scala_Types/index.html b/docs/Scala/Scala_Types/index.html deleted file mode 100644 index d5e1f6e..0000000 --- a/docs/Scala/Scala_Types/index.html +++ /dev/null @@ -1,2345 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scala Types - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Scala Types

- -

Type Refinement

-

Type Refinement = "subclassing without naming the subclass".

-
class Entity
-
-trait Persister {
-  def doPersist(e: Entity) = {
-    e.persistForReal()
-  }
-}
-
-// our refined instance (and type):
-val refinedMockPersister = new Persister {  
-  override def doPersist(e: Entity) = ()   
-}
-
- -

Scala Types of Types

-

Generics

-
class Reference[T] {
-    private var contents: T = _             // _ represents a default value. This default value is 0 for numeric types, false for the Boolean type, () for the Unit type and null for all object types.
-    def set(value: T) { contents = value }
-    def get: T = contents
-}
-
-trait Cache[K, V] {
-      def get(key: K): V
-      def put(key: K, value: V)
-      def delete(key: K)
-    }
-
-def remove[K](key: K)  // function
-
- -

Type Variance

-

Covariance +A allow you to set the your container to a either a variable with the same type or parent type.

-
class MyContainer[+A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {
-      private[this] val item = a
-
-      def get = item
-
-      def contents = manifest.runtimeClass.getSimpleName
-    }
-
-    val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange())
-    fruitBasket.contents
-
- -

Contravariance -A is the opposite of covariance

-

Declaring neither -/+, indicates invariance variance. You cannot use a superclass variable reference ("contravariant" position) or a subclass variable reference ("covariant" position) of that type.

-

Upper and Lower Type Bounds

-
abstract class Pet extends Animal { def name: String }
-
-class Cat extends Pet {
-  override def name: String = "Cat"
-}
-
-class PetContainer[P <: Pet](p: P) {
-  def pet: P = p   // The class PetContainer take a type parameter P which must be a subtype of Pet.
-}
-
- -

Lower type bounds declare a type to be a supertype of another type. The term B >: A expresses that the type parameter B or the abstract type B refer to a supertype of type A.

-

Abstract Types

-
type R = Double // type alias
-
- -
trait Container {
-  type T
-  val data: T
-
-  def compare(other: T) = data.equals(other)
-}
-
-class StringContainer(val data: String) extends Container {
-  override type T = String
-}
-
- -

Generics vs Abstract Types

-

Generics:

-
    -
  • If you need just type instantiation. A good example is the standard collection classes.
  • -
  • If you are creating a family of types.
  • -
-

Abstract types:

-
    -
  • If you want to allow people to mix in types using traits.
  • -
  • If you need better readability in scenarios where both could be interchangeable.
  • -
  • If you want to hide the type definition from the client code.
  • -
-

Infix Type

-

We can make a type infix, meaning that a generic type with two type parameters can be displayed between two types. -The type specifier Pair[String,Int] can be written as String Pair Int.

-
class Pair[A, B](a: A, b: B)
-
-type ~[A,B] = Pair[A,B]
-val pairlist: List[String ~ Int]   // operator-like usage
-
-case class Item[T](i: T) {
-    def ~(j: Item[T]) = new Pair(this, j)  // creating an infix operator method to use with our infix type
-}
-
-(Item("a") ~ Item("b")).isInstanceOf[String ~ String]
-
- -

ShapeLess

-

Structural Types

-
import scala.language.reflectiveCalls   // use reflection --> slow
-
-def onlyThoseThatCanPerformQuacks(quacker: {def quack:String}): String = {
-        "received message: %s".format(quacker.quack)
-      }
-
-type SpeakerAndMover = {def speak:String; def move(steps:Int, direction:String):String}  // with type aliasing
-
- -

Self-type

-

Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn’t directly extend it. That makes the members of the dependency available without imports.

-
trait User {
-  def username: String
-}
-
-trait Tweeter {
-  this: User =>  // reassign this
-  def tweet(tweetText: String) = println(s"$username: $tweetText")
-}
-
-class VerifiedTweeter(val username_ : String) extends Tweeter with User {  // We mixin User because Tweeter required it
-  def username = s"real $username_"
-}
-
- -

Difference between a self type and extending a trait

-
    -
  • If you say that B extends A, then B is an A. When you use self-types, B requires an A.
  • -
-

There are two specific requirements that are created with self-types: -1. If B is extended, then you're required to mix-in an A. -1. When a concrete class finally extends/mixes-in these traits, some class/trait must implement A.

-
trait Wrong extends Tweeter {
-     def noCanDo = name        // does not compile
-}
-
- -

If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error.

-
    -
  • Self types allow you to define cyclical dependencies. For example, you can achieve this:
  • -
-
trait A { self: B => }
-trait B { self: A => }
-
- -

Inheritance using extends does not allow that.

-
    -
  • Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as:
  • -
-
sealed trait Person
-trait Student extends Person
-trait Teacher extends Person
-trait Adult { this : Person => } // orthogonal to its condition
-
-val p : Person = new Student {}
-p match {
-  case s : Student => println("a student")
-  case t : Teacher => println("a teacher")
-} // that's it we're exhaustive
-
- -

Implicits

-

Implicits wrap around existing classes to provide extra functionality

-
object MyPredef {   // usually in a companion object
-
-  class IntWrapper(val original: Int) {
-    def isOdd = original % 2 != 0
-    def isEven = !isOdd
-  }
-
-  implicit def thisMethodNameIsIrrelevant(value: Int) = new IntWrapper(value)
-}
-
-import MyPredef._
-//imported implicits come into effect within this scope
-19.isOdd
-
-// Implicits can be used to automatically convert one type to another
-import java.math.BigInteger
-implicit def Int2BigIntegerConvert(value: Int): BigInteger = new BigInteger(value.toString)
-def add(a: BigInteger, b: BigInteger) = a.add(b)
-add(3, 6)  // 3 and 6 are Int
-
-// Implicits function parameters
-def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName
-implicit var hourlyRate = BigDecimal(34.00)
-implicit val currencyName = "Dollars"
-howMuchCanIMake_?(30)
-
- -

Default arguments though are preferred to Implicit Function Parameters.

-

Context-bound Types

-
def inspect[T : TypeTag](l: List[T]) = typeOf[T].typeSymbol.name.decoded
-val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
-inspect(list)
-
- -

equivalent to

-
def inspect[T](l: List[T])(implicit tt: TypeTag[T]) = tt.tpe.typeSymbol.name.decoded
-    val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
-    inspect(list)
-
- -

TypeTags can be used to determine a type used before it erased by the VM by using an implicit TypeTag argument.

- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/Scaladoc.md b/docs/Scala/Scaladoc.md similarity index 80% rename from docs_src/Scala/Scaladoc.md rename to docs/Scala/Scaladoc.md index a47a788..a90bbe8 100644 --- a/docs_src/Scala/Scaladoc.md +++ b/docs/Scala/Scaladoc.md @@ -3,26 +3,28 @@ [Scaladoc Style Guide](https://docs.scala-lang.org/style/scaladoc.html) - /** Start the comment here - * and use the left star followed by a - * white space on every line. - * - * Even on empty paragraph-break lines. - * - * Note that the * on each line is aligned - * with the second * in /** so that the - * left margin is on the same column on the - * first line and on subsequent ones. - * - * The closing Scaladoc tag goes on its own, - * separate line. E.g. - * - * Calculate the square of the given number - * - * @param d the Double to square - * @return the result of squaring d - */ - def square(d: Double): Double = d * d +```scala + /** Start the comment here + * and use the left star followed by a + * white space on every line. + * + * Even on empty paragraph-break lines. + * + * Note that the * on each line is aligned + * with the second * in /** so that the + * left margin is on the same column on the + * first line and on subsequent ones. + * + * The closing Scaladoc tag goes on its own, + * separate line. E.g. + * + * Calculate the square of the given number + * + * @param d the Double to square + * @return the result of squaring d + */ + def square(d: Double): Double = d * d +``` ## Tags @@ -87,31 +89,32 @@ before the group description. ### Macros -``@define `` allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of . +``@define `` allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of ``. - ## Markup - `monospace` - ''italic text'' - '''bold text''' - __underline__ - ^superscript^ - ,,subscript,, - [[entity link]], e.g. [[scala.collection.Seq]] - [[http://external.link External Link]], - e.g. [[http://scala-lang.org Scala Language Site]] - +```txt + `monospace` + ''italic text'' + '''bold text''' + __underline__ + ^superscript^ + ,,subscript,, + [[entity link]], e.g. [[scala.collection.Seq]] + [[https://external.link External Link]], + e.g. [[https://scala-lang.org Scala Language Site]] +``` + ## Other formatting notes -Paragraphs are started with one (or more) blank lines. +Paragraphs are started with one (or more) blank lines. ``*`` in the margin for the comment is valid (and should be included) but the line should be blank otherwise. -Code blocks are contained within {{{ this }}} and may be multi-line. +Code blocks are contained within {{{ this }}} and may be multi-line. Indentation is relative to the starting * for the comment. Headings are defined with surrounding = characters, with more = denoting subheadings. E.g. =Heading=, ==Sub-Heading==, etc. -List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles. \ No newline at end of file +List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles. diff --git a/docs/Scala/Scaladoc/index.html b/docs/Scala/Scaladoc/index.html deleted file mode 100644 index 6a88c06..0000000 --- a/docs/Scala/Scaladoc/index.html +++ /dev/null @@ -1,2155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Scaladoc - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Scaladoc

- -

Scaladoc -Scaladoc Style Guide

-
/** Start the comment here
-  * and use the left star followed by a
-  * white space on every line.
-  *
-  * Even on empty paragraph-break lines.
-  *
-  * Note that the * on each line is aligned
-  * with the second * in /** so that the
-  * left margin is on the same column on the
-  * first line and on subsequent ones.
-  *
-  * The closing Scaladoc tag goes on its own,
-  * separate line. E.g.
-  *
-  * Calculate the square of the given number
-  *
-  * @param d the Double to square
-  * @return the result of squaring d
-  */
- def square(d: Double): Double = d * d
-
- -

Tags

-

Class specific tags

-

@constructor placed in the class comment will describe the primary constructor. -Method specific tags

-

@return detail the return value from a method (one per method). -Method, Constructor and/or Class tags

-

@throws what exceptions (if any) the method or constructor may throw.

-

@param detail a value parameter for a method or constructor, provide one per parameter to the method/constructor.

-

@tparam detail a type parameter for a method, constructor or class. Provide one per type parameter.

-

Usage tags

-

@see reference other sources of information like external document links or related entities in the documentation.

-

@note add a note for pre or post conditions, or any other notable restrictions or expectations.

-

@example for providing example code or related example documentation.

-

@usecase provide a simplified method definition for when the full method definition is too complex or noisy. An example is (in the collections API), providing documentation for methods that omit the implicit canBuildFrom.

-

Member grouping tags

-

@group <group> - mark the entity as a member of the group.

-

@groupname <group> <name> - provide an optional name for the group. is displayed as the group header -before the group description.

-

@groupdesc <group> <description> - add optional descriptive text to display under the group name. Supports multiline formatted text.

-

@groupprio - control the order of the group on the page. Defaults to 0. Ungrouped elements have an implicit priority of 1000. Use a value between 0 and 999 to set a relative position to other groups. Low values will appear before high values.

-

Diagram tags

-

@contentDiagram - use with traits and classes to include a content hierarchy diagram showing included types. The diagram content can be fine tuned with additional specifiers taken from hideNodes, hideOutgoingImplicits, hideSubclasses, hideEdges, hideIncomingImplicits, hideSuperclasses and hideInheritedNode. hideDiagram can be supplied to prevent a diagram from being created if it would be created by default. Packages and objects have content diagrams by default.

-

@inheritanceDiagram

-

Other tags

-

@author provide author information for the following entity

-

@version the version of the system or API that this entity is a part of.

-

@since like @version but defines the system or API that this entity was first defined in.

-

@todo for documenting unimplemented features or unimplemented aspects of an entity.

-

@deprecated marks the entity as deprecated, providing both the replacement implementation that should be used and the version/date at which this entity was deprecated.

-

@migration like deprecated but provides advanced warning of planned changes ahead of deprecation. Same fields as @deprecated.

-

@inheritdoc take comments from a superclass as defaults if comments are not provided locally.

-

@documentable Expand a type alias and abstract type into a full template page. - TODO: Test the “abstract type” claim - no examples of this in the Scala code base

-

Macros

-

@define <name> <definition> allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of .

-

Markup

-
`monospace`
-''italic text''
-'''bold text'''
-__underline__
-^superscript^
-,,subscript,,
-[[entity link]], e.g. [[scala.collection.Seq]]
-[[http://external.link External Link]],
-  e.g. [[http://scala-lang.org Scala Language Site]]
-
- -

Other formatting notes

-

Paragraphs are started with one (or more) blank lines.

-

* in the margin for the comment is valid (and should be included) but the line should be blank otherwise.

-

Code blocks are contained within {{{ this }}} and may be multi-line.

-

Indentation is relative to the starting * for the comment.

-

Headings are defined with surrounding = characters, with more = denoting subheadings. E.g. =Heading=, ==Sub-Heading==, etc.

-

List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles.

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Scala/sbt.md b/docs/Scala/sbt.md similarity index 95% rename from docs_src/Scala/sbt.md rename to docs/Scala/sbt.md index b20bb27..25e6833 100644 --- a/docs_src/Scala/sbt.md +++ b/docs/Scala/sbt.md @@ -1,7 +1,7 @@ ## SBT Links -[SBT Home Page](http://www.scala-sbt.org/) +[SBT Home Page](https://www.scala-sbt.org/) [Scala school's SBT page](https://twitter.github.io/scala_school/sbt.html) @@ -20,12 +20,11 @@ $ sbt [Giter8 templates](https://github.com/foundweekends/giter8/wiki/giter8-templates) - ## Layout sbt uses the same directory structure as Maven for source files by default (all paths are relative to the base directory): -``` +```txt src/ main/ resources/ @@ -47,13 +46,12 @@ Other directories in ``src/`` will be ignored. Additionally, all hidden director Source code can be placed in the project’s base directory as ``hello/app.scala``, which may be for small projects, though for normal projects people tend to keep the projects in the src/main/ directory to keep things neat. - ## Build Definition The build definition goes in a file called ``build.sbt``, located in the project’s base directory. The “base directory” is the directory containing the project. In addition to ``build.sbt``, the project directory can contain .scala files that defines helper objects and one-off plugins. -``` +```txt build.sbt project/ Dependencies.scala @@ -61,14 +59,14 @@ project/ ``.gitignore`` (or equivalent for other version control systems) should contain: -``` +```txt target/ ``` -As part of your build definition, specify the version of ``sbt`` that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. +As part of your build definition, specify the version of ``sbt`` that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. To do this, create a file named ``project/build.properties`` that specifies the sbt version as follows: -``` +```txt sbt.version=1.0.2 ``` @@ -89,19 +87,17 @@ Those should go in the ``project/`` directory as Scala source files. There are three flavors of key: -``` +```txt SettingKey[T]: a key for a value computed once (the value is computed when loading the subproject, and kept around). TaskKey[T]: a key for a value, called a task, that has to be recomputed each time, potentially with side effects. InputKey[T]: a key for a task that has command line arguments as input. Check out Input Tasks for more details. ``` - -### Built-in Keys +### Built-in Keys The built-in keys are just fields in an object called Keys. A ``build.sbt`` implicitly has an ``import sbt.Keys._``, so sbt.Keys.name can be referred to as name. - -### Adding Library Dependencies +### Adding Library Dependencies To depend on third-party libraries, there are two options. The first is to drop jars in ``lib/`` (unmanaged dependencies) and the other is to add managed dependencies, which will look like this in ``build.sbt``: @@ -122,5 +118,5 @@ lazy val root = (project in file(".")) ) ``` -The libraryDependencies key involves two complexities: ``+=`` rather than ``:=``, and the ``%`` method. ``+=`` appends to the key’s old value rather than replacing it. +The libraryDependencies key involves two complexities: ``+=`` rather than ``:=``, and the ``%`` method. ``+=`` appends to the key’s old value rather than replacing it. The ``%`` method is used to construct an Ivy module ID from strings. diff --git a/docs/Scala/sbt/index.html b/docs/Scala/sbt/index.html deleted file mode 100644 index 90bf617..0000000 --- a/docs/Scala/sbt/index.html +++ /dev/null @@ -1,2127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Sbt - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Sbt

- - -

SBT Home Page

-

Scala school's SBT page

-

SBT: The Missing Tutorial

-

Create a New Project

-
$ sbt new sbt/scala-seed.g8
-$ cd hello
-$ sbt
-...
-> run
-> exit
-
- -

Giter8 templates

-

Layout

-

sbt uses the same directory structure as Maven for source files by default (all paths are relative to the base directory):

-
src/
-  main/
-    resources/
-       <files to include in main jar here>
-    scala/
-       <main Scala sources>
-    java/
-       <main Java sources>
-  test/
-    resources
-       <files to include in test jar here>
-    scala/
-       <test Scala sources>
-    java/
-       <test Java sources>
-
- -

Other directories in src/ will be ignored. Additionally, all hidden directories will be ignored.

-

Source code can be placed in the project’s base directory as hello/app.scala, which may be for small projects, though for normal projects people tend to keep the projects in the src/main/ directory to keep things neat.

-

Build Definition

-

The build definition goes in a file called build.sbt, located in the project’s base directory. The “base directory” is the directory containing the project. -In addition to build.sbt, the project directory can contain .scala files that defines helper objects and one-off plugins.

-
build.sbt
-project/
-  Dependencies.scala
-
- -

.gitignore (or equivalent for other version control systems) should contain:

-
target/
-
- -

As part of your build definition, specify the version of sbt that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. -To do this, create a file named project/build.properties that specifies the sbt version as follows:

-
sbt.version=1.0.2
-
- -

A build definition is defined in build.sbt, and it consists of a set of projects (of type Project). Because the term project can be ambiguous, we often call it a subproject.

-
lazy val root = (project in file("."))
-  .settings(
-    name := "Hello",
-    scalaVersion := "2.12.3"
-  )
-
- -

Each subproject is configured by key-value pairs.

-

build.sbt may also be interspersed with vals, lazy vals, and defs. Top-level objects and classes are not allowed in build.sbt. -Those should go in the project/ directory as Scala source files.

-

There are three flavors of key:

-
SettingKey[T]: a key for a value computed once (the value is computed when loading the subproject, and kept around).
-TaskKey[T]: a key for a value, called a task, that has to be recomputed each time, potentially with side effects.
-InputKey[T]: a key for a task that has command line arguments as input. Check out Input Tasks for more details.
-
- -

Built-in Keys

-

The built-in keys are just fields in an object called Keys. A build.sbt implicitly has an import sbt.Keys._, so sbt.Keys.name can be referred to as name.

-

Adding Library Dependencies

-

To depend on third-party libraries, there are two options. The first is to drop jars in lib/ (unmanaged dependencies) and the other is to add managed dependencies, which will look like this in build.sbt:

-
val derby = "org.apache.derby" % "derby" % "10.4.1.3"
-
-lazy val commonSettings = Seq(
-  organization := "com.example",
-  version := "0.1.0-SNAPSHOT",
-  scalaVersion := "2.12.3"
-)
-
-lazy val root = (project in file("."))
-  .settings(
-    commonSettings,
-    name := "Hello",
-    libraryDependencies += derby
-  )
-
- -

The libraryDependencies key involves two complexities: += rather than :=, and the % method. += appends to the key’s old value rather than replacing it. -The % method is used to construct an Ivy module ID from strings.

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Search/ElasticSearch.md b/docs/Search/ElasticSearch.md similarity index 84% rename from docs_src/Search/ElasticSearch.md rename to docs/Search/ElasticSearch.md index 0db0962..7c4424c 100644 --- a/docs_src/Search/ElasticSearch.md +++ b/docs/Search/ElasticSearch.md @@ -6,38 +6,36 @@ tags: IR ## Cheatsheets -[Jolicode](http://elasticsearch-cheatsheet.jolicode.com/) - +[Jolicode](https://elasticsearch-cheatsheet.jolicode.com/) ## Development URLs -[Kibana (port 5601)](http://localhost:5601) - -[Sense](http://localhost:5601/app/sense) +[Kibana (port 5601)](https://localhost:5601) -[ElasticSearch (port 9200)](http://localhost:9200) +[Sense](https://localhost:5601/app/sense) +[ElasticSearch (port 9200)](https://localhost:9200) ## INSTALL -1. Install [curl](http://curl.haxx.se/download.html) -2. Install [Java](http://www.java.com) +1. Install [curl](https://curl.haxx.se/download.html) +2. Install [Java](https://www.java.com) 3. Download [ElasticSearch](https://www.elastic.co/downloads/elasticsearch) 4. Optionally change the `cluster.name` in the `elasticsearch.yml` configuration ```bash cd elasticsearch- ./bin/elasticsearch -d -# or on Windows +# or on Windows # bin\elasticsearch.bat -curl 'http://localhost:9200/?pretty' +curl 'https://localhost:9200/?pretty' ``` -5. Install [Kibana](https://www.elastic.co/downloads/kibana) +5. Install [Kibana](https://www.elastic.co/downloads/kibana) * Open `config/kibana.yml` in an editor * Set the elasticsearch.url to point at your Elasticsearch instance * Run `./bin/kibana` (orbin\kibana.bat on Windows) - * Point your browser at [http://localhost:5601](http://localhost:5601) + * Point your browser at [https://localhost:5601](https://localhost:5601) 6. Install [Sense](https://www.elastic.co/guide/en/elasticsearch/guide/current/running-elasticsearch.html#sense) @@ -45,28 +43,28 @@ curl 'http://localhost:9200/?pretty' ./bin/kibana plugin --install elastic/sense ``` -*On Windows:* +*On Windows:* ```bash bin\kibana.bat plugin --install elastic/sense -``` -Then go to +``` -[http://localhost:5601/app/sense](http://localhost:5601/app/sense) +Then go to +[https://localhost:5601/app/sense](https://localhost:5601/app/sense) ## CURL ```bash curl -X '://:/?' -d '' ``` - + *verb is GET, POST, PUT, HEAD, or DELETE* ### Examples ```bash -curl -XGET 'http://localhost:9200/_count?pretty' -d '{ "query": { "match_all": {} }}' +curl -XGET 'https://localhost:9200/_count?pretty' -d '{ "query": { "match_all": {} }}' ``` ```bash @@ -89,6 +87,7 @@ PUT index/type/1 "body": "here" } ``` + and retrieve it ``` @@ -99,46 +98,48 @@ GET index/type/1 **URL pattern** -`http://yournode:9200/_plugin/` +`https://yournode:9200/_plugin/` On Debian, the script is in: `/usr/share/elasticsearch/bin/plugin`. -__Install various plugins__ +**Install various plugins** ```bash ./bin/plugin --install mobz/elasticsearch-head ./bin/plugin --install lmenezes/elasticsearch-kopf/1.2 ./bin/plugin --install elasticsearch/marvel/latest ``` -__Remove a plugin__ +**Remove a plugin** ```bash ./bin/plugin --remove ``` -__List installed plugins__ +**List installed plugins** ```bash ./bin/plugin --list ``` + ``` GET /_nodes?plugin=true ``` + [Elasticsearch monitoring and management plugins](https://blog.codecentric.de/en/2014/03/elasticsearch-monitoring-and-management-plugins/) **Head** -[Head](http://mobz.github.io/elasticsearch-head/) +[Head](https://mobz.github.io/elasticsearch-head/) 1. `elasticsearch/bin/plugin -install mobz/elasticsearch-head` -2. open [http://localhost:9200/_plugin/head](http://localhost:9200/_plugin/head) +2. open [https://localhost:9200/_plugin/head](https://localhost:9200/_plugin/head) -[elastichq.org](http://www.elastichq.org/) +[elastichq.org](https://www.elastichq.org/) **BigDesk** -Live charts and statistics for elasticsearch cluster: -[BigDesk](http://bigdesk.org/) +Live charts and statistics for elasticsearch cluster: +[BigDesk](https://bigdesk.org/) **Kopf** @@ -160,7 +161,7 @@ Live charts and statistics for elasticsearch cluster: **Aspire** -[Aspire](http://www.searchtechnologies.com/aspire-for-elasticsearch) +[Aspire](https://www.searchtechnologies.com/aspire-for-elasticsearch) Aspire is a framework and libraries of extensible components designed to enable creation of solutions to acquire data from one or more content repositories (such as file systems, relational databases, cloud storage, or content management systems), extract metadata and text from the documents, analyze, modify and enhance the content and metadata if needed, and then publish each document, together with its metadata, to a search engine or other target application @@ -170,7 +171,7 @@ Aspire is a framework and libraries of extensible components designed to enable [Integration with Hadoop](https://www.elastic.co/guide/en/elasticsearch/hadoop/current/index.html) -[Bulk loading for elastic search http://infochimps.com](https://github.com/infochimps-labs/wonderdog) +[Bulk loading for elastic search https://infochimps.com](https://github.com/infochimps-labs/wonderdog) **Integration with Spring** @@ -184,75 +185,72 @@ Aspire is a framework and libraries of extensible components designed to enable BI platforms that can use ES as an analytics engine: -- Kibana -- [Grafana](grafana.org/) -- BIRT - * [Birt](http://developer.actuate.com/community/forum/index.php?/topic/36913-birt-web-service-rest-json/?p=138062) - * [Birt](http://developer.actuate.com/community/forum/index.php?/topic/36913-birt-web-service-rest-json/?p=138062) - +* Kibana +* [Grafana](https://grafana.org/) +* BIRT + * [Birt](https://developer.actuate.com/community/forum/index.php?/topic/36913-birt-web-service-rest-json/?p=138062) + * [Birt](https://developer.actuate.com/community/forum/index.php?/topic/36913-birt-web-service-rest-json/?p=138062) -- Adminer - - [Adminer.org](https://www.adminer.org/) - - Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: [WAMP](https://bitnami.com/stack/wamp) +* Adminer + * [Adminer.org](https://www.adminer.org/) + * Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: [WAMP](https://bitnami.com/stack/wamp) -- Mongolastic - - A tool that migrates data from MongoDB to Elasticsearch and vice versa - - [Mongolastic](https://github.com/ozlerhakan/mongolastic) +* Mongolastic + * A tool that migrates data from MongoDB to Elasticsearch and vice versa + * [Mongolastic](https://github.com/ozlerhakan/mongolastic) -- Elasticsearch-exporter - - [Elasticsearch-exporter](https://github.com/mallocator/Elasticsearch-Exporter) +* Elasticsearch-exporter + * [Elasticsearch-exporter](https://github.com/mallocator/Elasticsearch-Exporter) ## Code Examples - developing a Web UI for ES -- [Sitepoint](https://www.sitepoint.com/building-recipe-search-site-angular-elasticsearch/) -- [CottageLabs](https://github.com/CottageLabs/facetview2) -- [scrutmydocs.org](http://www.scrutmydocs.org/) -- [qbox.io](https://qbox.io/blog/series/machine-learning) +* [Sitepoint](https://www.sitepoint.com/building-recipe-search-site-angular-elasticsearch/) +* [CottageLabs](https://github.com/CottageLabs/facetview2) +* [scrutmydocs.org](https://www.scrutmydocs.org/) +* [qbox.io](https://qbox.io/blog/series/machine-learning) ## Java API -- [Java clients](https://www.elastic.co/blog/found-java-clients-for-elasticsearch) -- [elasticsearch tutorial](https://github.com/jaibeermalik/elasticsearch-tutorial) -- [elasticsearchfr/](https://github.com/elasticsearchfr/hands-on) -- [IBM](http://www.ibm.com/developerworks/library/j-use-elasticsearch-java-apps/index.html) -- [dzone](https://dzone.com/articles/elasticsearch-java-api) - +* [Java clients](https://www.elastic.co/blog/found-java-clients-for-elasticsearch) +* [elasticsearch tutorial](https://github.com/jaibeermalik/elasticsearch-tutorial) +* [elasticsearchfr/](https://github.com/elasticsearchfr/hands-on) +* [IBM](https://www.ibm.com/developerworks/library/j-use-elasticsearch-java-apps/index.html) +* [dzone](https://dzone.com/articles/elasticsearch-java-api) # BASICS An Elasticsearch cluster can contain multiple indices, which in turn contain multiple types. These types hold multiple documents, and each document has multiple fields. - ## Explore (using Sense) `GET _stats/` \# List indices -``` +```txt GET /_cat/indices/ GET /_cat/indices/my_ind* ``` \# Get info about one index -``` +```txt GET /twitter GET /my_index_nr_1*/_settings?pretty or ?v GET /twitter/_settings,_mappings ``` -The available features are _settings, _mappings, _warmers and _aliases +The available features are _settings,_mappings, _warmers and_aliases \# cluster -``` +```txt GET /_nodes ``` \# insert data -``` +```txt PUT my_index/user/1 { "first_name": "John", @@ -263,7 +261,7 @@ PUT my_index/user/1 \#search -``` +```txt GET my_index/_search GET _count?pretty @@ -271,15 +269,13 @@ GET _count?pretty \# Data schema -``` +```txt GET my_index/_mapping ``` - - ## INSERT DOCUMENTS -``` +```txt PUT /index/type/ID PUT /megacorp/employee/1 { "first_name" : "John", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests": [ "sports", "music" ]} @@ -295,7 +291,7 @@ Every document in Elasticsearch has a version number. Every time a change is mad *Optimistic concurrency control* -``` +```txt PUT /website/blog/1?version=1 { "title": "My first blog entry", "text": "Starting to get the hang of this..."} We want this update to succeed only if the current _version of this document in our index is version 1 @@ -307,17 +303,18 @@ PUT /website/blog/2?version=5&version_type=external { "title": "My first externa ## INSERT DOCUMENTS - AUTOGENERATED IDS -``` +```txt POST /website/blog/ { "title": "My second blog entry", "text": "Still trying this out...", "date": "2014/01/01" } -``` +``` Response: -``` + +```txt { "_index": "website", "_type": "blog", @@ -329,34 +326,35 @@ Response: \# creating an entirely new document and not overwriting an existing one -``` +```txt PUT /website/blog/123?op_type=create { ... } PUT /website/blog/123/_create { ... } ``` ## RETRIEVE DOCUMENTS -``` +```txt GET /website/blog/123 # optional ?pretty ``` + { "_index" : "website", "_type" : "blog", "_id" : "123", "_version" : 1, "found" : true, "_source" : { "title": "My first blog entry", "text": "Just trying this out...", "date": "2014/01/01" }} \# Contains just the fields that we requested -``` +```txt GET /website/blog/123?_source=title,text ``` \# Just get the original doc -``` +```txt GET /website/blog/123/_source ``` \# check if doc exists -- HTTP 200 or 404 ```bash -curl -i -XHEAD http://localhost:9200/website/blog/123 +curl -i -XHEAD https://localhost:9200/website/blog/123 ``` \# Note: HEAD/exists requests do not work in Sense @@ -365,7 +363,7 @@ curl -i -XHEAD http://localhost:9200/website/blog/123 \# multiple docs at once -``` +```txt GET /website/blog/_mget { "ids" : [ "2", "1" ]} ``` @@ -375,47 +373,47 @@ Documents in Elasticsearch are immutable; we cannot change them. Instead, if we \# Accepts a partial document as the doc parameter, which just gets merged with the existing document. -``` +```txt POST /website/blog/1/_update { "doc" : { "tags" : [ "testing" ], "views": 0 }} ``` \# Script - -``` + +```txt POST /website/blog/1/_update { "script" : "ctx._source.views+=1"} ``` \# script with parameters -``` +```txt POST /website/blog/1/_update { "script" : "ctx._source.tags+=new_tag", "params" : { "new_tag" : "search" }} ``` \# upsert -``` +```txt POST/website/pageviews/1/_update {"script":"ctx._source.views+=1","upsert":{"views":1}} ``` ## DELETE -``` +```txt DELETE /website/blog/123 ``` \# delete doc based on its contents -``` +```txt POST /website/blog/1/_update { "script" : "ctx.op = ctx._source.views == count ? 'delete' : 'none'", "params" : { "count": 1 }} ``` ## BULK -``` +```txt POST /_bulk {"delete":{"_index":"website","_type":"blog","_id":"123"}} {"create":{"_index":"website","_type":"blog","_id":"123"}} # Create a document only if the document does not already exist @@ -428,7 +426,7 @@ POST /_bulk Bulk in the same index or index/type -``` +```txt POST /website/_bulk {"index":{"_type":"log"}} {"event":"User logged in"} @@ -438,27 +436,26 @@ POST /website/_bulk Try around 5-15MB in size. - ## SEARCH Every field in a document is indexed and can be queried. \# Search for all employees in the megacorp index: -``` +```txt GET /megacorp/employee/_search ``` \# Search for all employees in the megacorp index \# who have "Smith" in the last_name field -``` +```txt GET /megacorp/employee/_search?q=last_name:Smith ``` \# Same query as above, but using the Query DSL -``` +```txt GET /megacorp/employee/_search { "query": { @@ -471,19 +468,19 @@ GET /megacorp/employee/_search \# SEARCH QUERY STRING -``` +```txt GET /_all/tweet/_search?q=tweet:elasticsearch ``` Don't forget to URL encode special characters e.g. +name:john +tweet:mary -``` +```txt GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary ``` The + prefix indicates conditions that must be satisfied for our query to match. Similarly a - prefix would indicate conditions that must not match. All conditions without a + or - are optional -``` +```txt +name:(mary john) +date:>2014-09-10 +(aggregations geo) # last part searches _all ``` @@ -492,7 +489,7 @@ The + prefix indicates conditions that must be satisfied for our query to match. When used in filtering context, the query is said to be a "non-scoring" or "filtering" query. That is, the query simply asks the question: "Does this document match?". The answer is always a simple, binary yes|no. When used in a querying context, the query becomes a "scoring" query. -``` +```txt # Find all employees whose `last_name` is Smith # and who are older than 30 GET /megacorp/employee/_search @@ -518,7 +515,7 @@ GET /megacorp/employee/_search \# Find all employees who enjoy "rock" or "climbing" -``` +```txt GET /megacorp/employee/_search { "query" : { @@ -535,7 +532,7 @@ If you use it on a field containing an exact value, such as a number, a date, a ## MATCH ON MULTIPLE FIELDS -``` +```txt { "multi_match": { "query": "full text search", @@ -547,7 +544,7 @@ If you use it on a field containing an exact value, such as a number, a date, a \# Find all employees who enjoy "rock climbing" -``` +```txt GET /megacorp/employee/_search { "query" : { @@ -564,7 +561,7 @@ The term query is used to search by exact values, be they numbers, dates, Boolea The terms query is the same as the term query, but allows you to specify multiple values to match. If the field contains any of the specified values, the document matches -``` +```txt { "terms": { "tag": [ "search", "full_text", "nosql" ] }} ``` @@ -583,12 +580,10 @@ The terms query is the same as the term query, but allows you to specify multipl GET /gb/tweet/_validate/query?explain { "query": { "tweet" : { "match" : "really powerful" } }} - \# understand why one particular document matched or, more important, why it didn’t match GET /us/tweet/12/_explain { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 2 }}, "must" : { "match" : { "tweet" : "honeymoon" }} } }} - ## MULTIPLE INDICES OR TYPES # all documents all indices @@ -609,7 +604,6 @@ The terms query is the same as the term query, but allows you to specify multipl /_all/user,tweet/_search Search types user and tweet in all indices - ## PAGINATION GET /_search?size=5GET /_search?size=5&from=5 @@ -629,7 +623,6 @@ then sort on the new field GET /_search { "query": { "match": { "tweet": "elasticsearch" } }, "sort": "tweet.raw"} - ## HIGHLIGHTS \# Find all employees who enjoy "rock climbing" - highlights @@ -649,7 +642,6 @@ then sort on the new field } } - ## ANALYSIS An analyzer is really just a wrapper that combines three functions into a single package: @@ -666,7 +658,6 @@ An analyzer is really just a wrapper that combines three functions into a single GET /gb/_analyze { "field": "tweet", "text": "Black-cats"} - ## MAPPINGS (schemas) Every type has its own mapping, or schema definition. A mapping defines the fields within a type, the datatype for each field, and how the field should be handled by Elasticsearch. A mapping is also used to configure metadata associated with the type. @@ -675,11 +666,12 @@ You can control dynamic nature of mappings Mapping (or schema definition) for the tweet type in the gb index -``` +```txt GET /gb/_mapping/tweet ``` Elasticsearch supports the following simple field types: + * String: string * Whole number: byte, short, integer, long * Floating-point: float, double @@ -690,12 +682,14 @@ Fields of type string are, by default, considered to contain full text. That is, The two most important mapping attributes for string fields are index and analyzer. The index attribute controls how the string will be indexed. It can contain one of three values: + * analyzed First analyze the string and then index it. In other words, index this field as full text. * not_analyzed Index this field, so it is searchable, but index the value exactly as specified. Do not analyze it. * no Don’t index this field at all. This field will not be searchable. If we want to map the field as an exact value, we need to set it to not_analyzed: -``` + +```txt { "tag": { "type": "string", @@ -705,7 +699,8 @@ If we want to map the field as an exact value, we need to set it to not_analyzed ``` For analyzed string fields, use the analyzer attribute to specify which analyzer to apply both at search time and at index time. By default, Elasticsearch uses the standard analyzer, but you can change this by specifying one of the built-in analyzers, such as whitespace, simple, or english: -``` + +```txt { "tweet": { "type": "string", @@ -905,21 +900,19 @@ Aggregations and searches can span multiple indices } } - ## INDEX MANAGEMENT By default, indices are assigned five primary shards. The number of primary shards can be set only when an index is created and never changed \# Add an index -``` +```txt PUT /blogs { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 }} PUT /blogs/_settings { "number_of_replicas" : 2} ``` -- ElasticSearch Shards should be 50 GB or less in size. -- Use aliases to shelter the underlying index (or indices) and allow index swapping - +* ElasticSearch Shards should be 50 GB or less in size. +* Use aliases to shelter the underlying index (or indices) and allow index swapping ## CLUSTER MANAGEMENT @@ -927,40 +920,42 @@ By default, indices are assigned five primary shards. The number of primary shar ## CONFIGURATION -- config directory -- yaml file +* config directory +* yaml file -- Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache -- Prefer not to allocate 30GB !! --> uncompressed pointers -- Never let the JVM swap bootstrap.mlockall = true -- Keep the JVM defaults -- Do not use G1GC alternative garbage collector +* Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache +* Prefer not to allocate 30GB !! --> uncompressed pointers +* Never let the JVM swap bootstrap.mlockall = true +* Keep the JVM defaults +* Do not use G1GC alternative garbage collector -``` +```txt cluster.name: ``` -- All nodes in the cluster must have the same cluster name +* All nodes in the cluster must have the same cluster name -``` +```txt node.name: ``` -``` + +```txt ./bin/elasticsearch --node.name=`hostname` ``` + to override the configuration file -- HTTP port: 9200 and successors -- Transport : 9300 (internal communications) +* HTTP port: 9200 and successors +* Transport : 9300 (internal communications) ### Discovery -- AWS plugin available --> also include integration with S3 (snapshot to S3) -- AWS: multi-AZ is OK but replication across far data centers is not recommended -- See: resiliency +* AWS plugin available --> also include integration with S3 (snapshot to S3) +* AWS: multi-AZ is OK but replication across far data centers is not recommended +* See: resiliency Sites plugins -- kopf / head / paramedic / bigdesk / kibana -- contain static web content (JS, HTML....) +* contain static web content (JS, HTML....) Install plugins on ALL machines of the cluster @@ -970,17 +965,18 @@ To install, ./bin/plugin install marvel-agent ./bin/plugin remove marvel-agent ``` + One type per index is recommended, except for parent child / nested indexes. index size optimization: -- can disable `_source` and `_all` (the index that captures every field - not needed unless the top search bar changes) -- by default, Kibana will search `_all` + +* can disable `_source` and `_all` (the index that captures every field - not needed unless the top search bar changes) +* by default, Kibana will search `_all` data types: string, number, bool, datetime, binary, array, object, geo_point, geo_shape, ip, multifield binary should be base64 encoded before storage - ### MAINTENANCE Steps to restore elastic search data: @@ -996,5 +992,3 @@ The commands to do the above are as below: 2. extract gz file to destination path 3. `systemctl start elasticsearch` 4. `systemctl daemon-reload elasticsearch` - - diff --git a/docs/Search/ElasticSearch/index.html b/docs/Search/ElasticSearch/index.html deleted file mode 100644 index 6dce54a..0000000 --- a/docs/Search/ElasticSearch/index.html +++ /dev/null @@ -1,2717 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - ElasticSearch Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Cheatsheets

-

Jolicode

-

Development URLs

-

Kibana (port 5601)

-

Sense

-

ElasticSearch (port 9200)

-

INSTALL

-
    -
  1. Install curl
  2. -
  3. Install Java
  4. -
  5. Download ElasticSearch
  6. -
  7. Optionally change the cluster.name in the elasticsearch.yml configuration
  8. -
-
cd elasticsearch-<version>
-./bin/elasticsearch -d
-# or on Windows 
-# bin\elasticsearch.bat
-curl 'http://localhost:9200/?pretty'
-
- -
    -
  1. -

    Install Kibana

    -
      -
    • Open config/kibana.yml in an editor
    • -
    • Set the elasticsearch.url to point at your Elasticsearch instance
    • -
    • Run ./bin/kibana (orbin\kibana.bat on Windows)
    • -
    • Point your browser at http://localhost:5601
    • -
    -
  2. -
  3. -

    Install Sense

    -
  4. -
-
./bin/kibana plugin --install elastic/sense
-
- -

On Windows:

-
bin\kibana.bat plugin --install elastic/sense
-
- -

Then go to

-

http://localhost:5601/app/sense

-

CURL

-
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
-
- -

verb is GET, POST, PUT, HEAD, or DELETE

-

Examples

-
curl -XGET 'http://localhost:9200/_count?pretty' -d '{ "query": { "match_all": {} }}'
-
- -
curl -XGET <id>.us-west-2.es.amazonaws.com
-
-curl -XGET 'https://<id>.us-west-2.es.amazonaws.com/_count?pretty' -d '{ "query": { "match_all": {} } }'
-
-curl -XPUT https://<id>.us-west-2.es.amazonaws.com/movies/movie/tt0116996 -d '{"directors" : ["Tim Burton"],"genres" : ["Comedy","Sci-Fi"], "plot": "The Earth is invaded by Martians with irresistible weapons and a cruel sense of humor.", "title" : "Mars Attacks!", "actors" :["Jack Nicholson","Pierce Brosnan","Sarah Jessica Parker"], "year" : 1996}'
-
- -

Sense

-

Sense syntax is similar to curl:

-

Index a document

-
PUT index/type/1
-{
- "body": "here"
-}
-
- -

and retrieve it

-
GET index/type/1
-
- -

PLUGINS

-

URL pattern

-

http://yournode:9200/_plugin/<plugin name>

-

On Debian, the script is in: /usr/share/elasticsearch/bin/plugin.

-

Install various plugins

-
./bin/plugin --install mobz/elasticsearch-head
-./bin/plugin --install lmenezes/elasticsearch-kopf/1.2
-./bin/plugin --install elasticsearch/marvel/latest
-
- -

Remove a plugin

-
./bin/plugin --remove
-
- -

List installed plugins

-
./bin/plugin --list
-
- -
GET /_nodes?plugin=true
-
- -

Elasticsearch monitoring and management plugins

-

Head

-

Head

-
    -
  1. elasticsearch/bin/plugin -install mobz/elasticsearch-head
  2. -
  3. open http://localhost:9200/_plugin/head
  4. -
-

elastichq.org

-

BigDesk

-

Live charts and statistics for elasticsearch cluster: -BigDesk

-

Kopf

-

Kopf

-
./bin/plugin --install lmenezes/elasticsearch-kopf/1.2`
-
- -

Marvel

-
./bin/plugin --install elasticsearch/marvel/latest
-
- -

Integrations (CMS, import/export, hadoop...)

-

Integrations

-

Aspire

-

Aspire

-

Aspire is a framework and libraries of extensible components designed to enable creation of solutions to acquire data from one or more content repositories (such as file systems, relational databases, cloud storage, or content management systems), extract metadata and text from the documents, analyze, modify and enhance the content and metadata if needed, and then publish each document, together with its metadata, to a search engine or other target application

-

Docs

-

Integration with Hadoop

-

Integration with Hadoop

-

Bulk loading for elastic search http://infochimps.com

-

Integration with Spring

-

Spring Data

-

WordPress

-

Wordpress

-

TOOLS

-

BI platforms that can use ES as an analytics engine:

-
    -
  • Kibana
  • -
  • Grafana
  • -
  • -

    BIRT

    - -
  • -
  • -

    Adminer

    -
      -
    • Adminer.org
    • -
    • Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: WAMP
    • -
    -
  • -
  • -

    Mongolastic

    -
      -
    • A tool that migrates data from MongoDB to Elasticsearch and vice versa
    • -
    • Mongolastic
    • -
    -
  • -
  • -

    Elasticsearch-exporter

    - -
  • -
-

Code Examples - developing a Web UI for ES

- -

Java API

- -

BASICS

-

An Elasticsearch cluster can contain multiple indices, which in turn contain multiple types. These types hold multiple documents, and each document has multiple fields.

-

Explore (using Sense)

-

GET _stats/

-

# List indices

-
GET /_cat/indices/
-GET /_cat/indices/my_ind*
-
- -

# Get info about one index

-
GET /twitter
-GET /my_index_nr_1*/_settings?pretty   or ?v
-GET /twitter/_settings,_mappings
-
- -

The available features are _settings, _mappings, _warmers and _aliases

-

# cluster

-
GET /_nodes
-
- -

# insert data

-
PUT my_index/user/1
-{
-"first_name":    "John",
-"last_name":     "Smith",
-"date_of_birth": "1970-10-24"
-}
-
- -

#search

-
GET my_index/_search
-
-GET _count?pretty
-
- -

# Data schema

-
GET my_index/_mapping
-
- -

INSERT DOCUMENTS

-
PUT /index/type/ID
-PUT /megacorp/employee/1
-{ "first_name" : "John", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests": [ "sports", "music" ]}
-
-PUT /megacorp/employee/2
-{ "first_name" : "Jane", "last_name" : "Smith", "age" : 32, "about" : "I like to collect rock albums", "interests": [ "music" ]}
-
-GET /megacorp/employee/1
-
- -

Field names can be any valid string, but may not include periods. -Every document in Elasticsearch has a version number. Every time a change is made to a document (including deleting it), the _version number is incremented.

-

Optimistic concurrency control

-
PUT /website/blog/1?version=1  { "title": "My first blog entry", "text": "Starting to get the hang of this..."}
-
-We want this update to succeed only if the current _version of this document in our index is version 1
-
-External version:
-
-PUT /website/blog/2?version=5&version_type=external { "title": "My first external blog entry", "text": "Starting to get the hang of this..."}
-
- -

INSERT DOCUMENTS - AUTOGENERATED IDS

-
POST /website/blog/
-{
-"title": "My second blog entry",
-"text":  "Still trying this out...",
-"date":  "2014/01/01"
-}
-
- -

Response:

-
{
-"_index":    "website",
-"_type":     "blog",
-"_id":       "AVFgSgVHUP18jI2wRx0w",
-"_version":  1,
-"created":   true
-}
-
- -

# creating an entirely new document and not overwriting an existing one

-
PUT /website/blog/123?op_type=create { ... }
-PUT /website/blog/123/_create { ... }
-
- -

RETRIEVE DOCUMENTS

-
GET /website/blog/123  # optional ?pretty
-
- -

{ "_index" : "website", "_type" : "blog", "_id" : "123", "_version" : 1, "found" : true, "_source" : { "title": "My first blog entry", "text": "Just trying this out...", "date": "2014/01/01" }}

-

# Contains just the fields that we requested

-
GET /website/blog/123?_source=title,text
-
- -

# Just get the original doc

-
GET /website/blog/123/_source
-
- -

# check if doc exists -- HTTP 200 or 404

-
curl -i -XHEAD http://localhost:9200/website/blog/123
-
- -

# Note: HEAD/exists requests do not work in Sense -# because they only return HTTP headers, not -# a JSON body

-

# multiple docs at once

-
GET /website/blog/_mget { "ids" : [ "2", "1" ]}
-
- -

UPDATE

-

Documents in Elasticsearch are immutable; we cannot change them. Instead, if we need to update an existing document, we reindex or replace it

-

# Accepts a partial document as the doc parameter, which just gets merged with the existing document.

-
POST /website/blog/1/_update
-{ "doc" : { "tags" : [ "testing" ], "views": 0 }}
-
- -

# Script

-
POST /website/blog/1/_update
-{ "script" : "ctx._source.views+=1"}
-
- -

# script with parameters

-
POST /website/blog/1/_update
-{ "script" : "ctx._source.tags+=new_tag", "params" : { "new_tag" : "search" }}
-
- -

# upsert

-
POST/website/pageviews/1/_update
-{"script":"ctx._source.views+=1","upsert":{"views":1}}
-
- -

DELETE

-
DELETE /website/blog/123
-
- -

# delete doc based on its contents

-
POST /website/blog/1/_update { "script" : "ctx.op = ctx._source.views == count ? 'delete' : 'none'", "params" : { "count": 1 }}
-
- -

BULK

-
POST /_bulk
-{"delete":{"_index":"website","_type":"blog","_id":"123"}}
-{"create":{"_index":"website","_type":"blog","_id":"123"}} #  Create a document only if the document does not already exist
-{"title":"My first blog post"}
-{"index":{"_index":"website","_type":"blog"}}
-{"title":"My second blog post"}
-{"update":{"_index":"website","_type":"blog","_id":"123","_retry_on_conflict":3}}
-{"doc":{"title":"My updated blog post"}}
-
- -

Bulk in the same index or index/type

-
POST /website/_bulk
-{"index":{"_type":"log"}}
-{"event":"User logged in"}
-{"index":{"_type":"blog"}}
-{"title":"My second blog post"}
-
- -

Try around 5-15MB in size.

- -

Every field in a document is indexed and can be queried.

-

# Search for all employees in the megacorp index:

-
GET /megacorp/employee/_search
-
- -

# Search for all employees in the megacorp index -# who have "Smith" in the last_name field

-
GET /megacorp/employee/_search?q=last_name:Smith
-
- -

# Same query as above, but using the Query DSL

-
GET /megacorp/employee/_search
-{
-    "query": {
-      "match": {
-        "last_name": "smith"
-      }
-    }
-}
-
- -

# SEARCH QUERY STRING

-
GET /_all/tweet/_search?q=tweet:elasticsearch
-
- -

Don't forget to URL encode special characters e.g. +name:john +tweet:mary

-
GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
-
- -

The + prefix indicates conditions that must be satisfied for our query to match. Similarly a - prefix would indicate conditions that must not match. All conditions without a + or - are optional

-
+name:(mary john) +date:>2014-09-10 +(aggregations geo) # last part searches _all
-
- -

QUERY DSL

-

When used in filtering context, the query is said to be a "non-scoring" or "filtering" query. That is, the query simply asks the question: "Does this document match?". The answer is always a simple, binary yes|no. -When used in a querying context, the query becomes a "scoring" query.

-
# Find all employees whose `last_name` is Smith
-# and who are older than 30
-GET /megacorp/employee/_search
-{
-"query" : {
-  "filtered" : {
-      "filter" : {
-      "range" : {
-          "age" : { "gt" : 30 }
-      }
-      },
-      "query" : {
-      "match" : {
-          "last_name" : "smith"
-      }
-      }
-  }
-}
-}
-
- -

MATCH

-

# Find all employees who enjoy "rock" or "climbing"

-
GET /megacorp/employee/_search
-{
-"query" : {
-  "match" : {
-      "about" : "rock climbing"
-  }
-}
-}
-
- -

The match query should be the standard query that you reach for whenever you want to query for a full-text or exact value in almost any field. -If you run a match query against a full-text field, it will analyze the query string by using the correct analyzer for that field before executing the search -If you use it on a field containing an exact value, such as a number, a date, a Boolean, or a not_analyzedstring field, then it will search for that exact value

-

MATCH ON MULTIPLE FIELDS

-
{
-"multi_match": {
-  "query":    "full text search",
-  "fields":  [ "title", "body" ]
-}}
-
- - -

# Find all employees who enjoy "rock climbing"

-
GET /megacorp/employee/_search
-{
-"query" : {
-  "match_phrase" : {
-      "about" : "rock climbing"
-  }
-}
-}
-
- -

# EXACT VALUES

-

The term query is used to search by exact values, be they numbers, dates, Booleans, or not_analyzed exact-value string fields

-

The terms query is the same as the term query, but allows you to specify multiple values to match. If the field contains any of the specified values, the document matches

-
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
-
- -

# Compound Queries

-

{ - "bool": { - "must": { "match": { "tweet": "elasticsearch" }}, - "must_not": { "match": { "name": "mary" }}, - "should": { "match": { "tweet": "full text" }}, - "filter": { "range": { "age" : { "gt" : 30 }} } - } - }

-

# VALIDATE A QUERY

-

GET /gb/tweet/_validate/query?explain { "query": { "tweet" : { "match" : "really powerful" } }}

-

# understand why one particular document matched or, more important, why it didn’t match

-

GET /us/tweet/12/_explain { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 2 }}, "must" : { "match" : { "tweet" : "honeymoon" }} } }}

-

MULTIPLE INDICES OR TYPES

-
# all documents all indices
-
- -

/_search

-

/gb,us/_search - Search all types in the gb and us indices

-

/g,u/_search - Search all types in any indices beginning with g or beginning with u

-

/gb/user/_search - Search type user in the gb index

-

/gb,us/user,tweet/_search - Search types user and tweet in the gb and us indices

-

/_all/user,tweet/_search - Search types user and tweet in all indices

-

PAGINATION

-
 GET /_search?size=5GET /_search?size=5&from=5
-
- -

SORTING

-
 GET /_search { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 1 }} } }, "sort": { "date": { "order": "desc" }}}
-
- -

For string sorting, use multi-field mapping:

-
 "tweet": { "type": "string", "analyzer": "english", "fields": { "raw": {"type": "string", "index": "not_analyzed" } }}
-
- -

The main tweet field is just the same as before: an analyzed full-text field. -The new tweet.raw subfield is not_analyzed.

-

then sort on the new field

-
 GET /_search { "query": { "match": { "tweet": "elasticsearch" } }, "sort": "tweet.raw"}
-
- -

HIGHLIGHTS

-

# Find all employees who enjoy "rock climbing" - highlights -# and highlight the matches

-

GET /megacorp/employee/_search - { - "query" : { - "match_phrase" : { - "about" : "rock climbing" - } - }, - "highlight": { - "fields" : { - "about" : {} - } - } - }

-

ANALYSIS

-

An analyzer is really just a wrapper that combines three functions into a single package:

-
* Character filters
-* Tokenizer
-* Token filters
-
- -

# See how text is analyzed

-

GET /_analyze { "analyzer": "standard", "text": "Text to analyze"}

-

# test analyzer

-

GET /gb/_analyze { "field": "tweet", "text": "Black-cats"}

-

MAPPINGS (schemas)

-

Every type has its own mapping, or schema definition. A mapping defines the fields within a type, the datatype for each field, and how the field should be handled by Elasticsearch. A mapping is also used to configure metadata associated with the type.

-

You can control dynamic nature of mappings

-

Mapping (or schema definition) for the tweet type in the gb index

-
  GET /gb/_mapping/tweet
-
- -

Elasticsearch supports the following simple field types: -* String: string -* Whole number: byte, short, integer, long -* Floating-point: float, double -* Boolean: boolean -* Date: date

-

Fields of type string are, by default, considered to contain full text. That is, their value will be passed through an analyzer before being indexed, and a full-text query on the field will pass the query string through an analyzer before searching. -The two most important mapping attributes for string fields are index and analyzer.

-

The index attribute controls how the string will be indexed. It can contain one of three values: -* analyzed First analyze the string and then index it. In other words, index this field as full text. -* not_analyzed Index this field, so it is searchable, but index the value exactly as specified. Do not analyze it. -* no Don’t index this field at all. This field will not be searchable.

-

If we want to map the field as an exact value, we need to set it to not_analyzed:

-
  {
-    "tag": {
-    "type": "string",
-    "index": "not_analyzed"
-    }
-  }
-
- -

For analyzed string fields, use the analyzer attribute to specify which analyzer to apply both at search time and at index time. By default, Elasticsearch uses the standard analyzer, but you can change this by specifying one of the built-in analyzers, such as whitespace, simple, or english:

-
  {
-    "tweet": {
-    "type": "string",
-    "analyzer": "english"
-    }
-  }
-
- -

# create a new index, specifying that the tweet field should use the english analyzer

-

PUT /gb - { "mappings": - { "tweet" : - { "properties" : { - "tweet" : { "type" : "string", "analyzer": "english" }, - "date" : { "type" : "date" }, - "name" : { "type" : "string" }, - "user_id" : { "type" : "long" } - }}}}

-

null, arrays, objects: see complex core fields

-

Parent Child Relationships

-
DELETE /test_index
-
-PUT /test_index
-{
-   "mappings": {
-      "parent_type": {
-         "properties": {
-            "num_prop": {
-               "type": "integer"
-            },
-            "str_prop": {
-               "type": "string"
-            }
-         }
-      },
-      "child_type": {
-         "_parent": {
-            "type": "parent_type"
-         },
-         "properties": {
-            "child_num": {
-               "type": "integer"
-            },
-            "child_str": {
-               "type": "string"
-            }
-         }
-      }
-   }
-}
-
-POST /test_index/_bulk
-{"index":{"_type":"parent_type","_id":1}}
-{"num_prop":1,"str_prop":"hello"}
-{"index":{"_type":"child_type","_id":1,"_parent":1}}
-{"child_num":11,"child_str":"foo"}
-{"index":{"_type":"child_type","_id":2,"_parent":1}}
-{"child_num":12,"child_str":"bar"}
-{"index":{"_type":"parent_type","_id":2}}
-{"num_prop":2,"str_prop":"goodbye"}
-{"index":{"_type":"child_type","_id":3,"_parent":2}}
-{"child_num":21,"child_str":"baz"}
-
-POST /test_index/child_type/_search
-
-POST /test_index/child_type/2?parent=1
-{
-   "child_num": 13,
-   "child_str": "bars"
-}
-
-POST /test_index/child_type/_search
-
-POST /test_index/child_type/3/_update?parent=2
-{
-   "script": "ctx._source.child_num+=1"
-}
-
-POST /test_index/child_type/_search
-
-POST /test_index/child_type/_search
-{
-    "query": {
-        "term": {
-           "child_str": {
-              "value": "foo"
-           }
-        }
-    }
-}
-
-POST /test_index/parent_type/_search
-{
-   "query": {
-      "filtered": {
-         "query": {
-            "match_all": {}
-         },
-         "filter": {
-            "has_child": {
-               "type": "child_type",
-               "filter": {
-                  "term": {
-                     "child_str": "foo"
-                  }
-               }
-            }
-         }
-      }
-   }
-}
-
- -

AGGREGATES

-

Aggregations and searches can span multiple indices

-

# Calculate the most popular interests for all employees

-

GET /megacorp/employee/_search - { - "aggs": { - "all_interests": { - "terms": { - "field": "interests" - } - } - } - }

-

# Calculate the most popular interests for -# employees named "Smith"

-

GET /megacorp/employee/_search - { - "query": { - "match": { - "last_name": "smith" - } - }, - "aggs": { - "all_interests": { - "terms": { - "field": "interests" - } - } - } - }

-

# Calculate the average age of employee per interest - hierarchical aggregates

-

GET /megacorp/employee/_search - { - "aggs" : { - "all_interests" : { - "terms" : { "field" : "interests" }, - "aggs" : { - "avg_age" : { - "avg" : { "field" : "age" } - } - } - } - } - }

-

# requires in config/elasticsearch.yml -# script.inline: true -# script.indexed: true

-

GET /tlo/contacts/_search - { - "size" : 0, - "query": { - "constant_score": { - "filter": { - "terms": { - "version": [ - "20160301", - "20160401" - ] - } - } - } - }, - "aggs": { - "counts": { - "cardinality": { - "script": "doc['first_name'].value + ' ' + doc['last_name'].value + ' ' + doc['company'].value", - "missing": "N/A" - } - } - } - }

-

INDEX MANAGEMENT

-

By default, indices are assigned five primary shards. The number of primary shards can be set only when an index is created and never changed

-

# Add an index

-
  PUT /blogs { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 }}
-  PUT /blogs/_settings { "number_of_replicas" : 2}
-
- -
    -
  • ElasticSearch Shards should be 50 GB or less in size.
  • -
  • Use aliases to shelter the underlying index (or indices) and allow index swapping
  • -
-

CLUSTER MANAGEMENT

-
 GET /_cluster/health
-
- -

CONFIGURATION

-
    -
  • config directory
  • -
  • -

    yaml file

    -
  • -
  • -

    Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache

    -
  • -
  • Prefer not to allocate 30GB !! --> uncompressed pointers
  • -
  • Never let the JVM swap bootstrap.mlockall = true
  • -
  • Keep the JVM defaults
  • -
  • Do not use G1GC alternative garbage collector
  • -
-
cluster.name: <my cluster>
-
- -
    -
  • All nodes in the cluster must have the same cluster name
  • -
-
node.name: <my_node_name>
-
- -
./bin/elasticsearch --node.name=`hostname`
-
- -

to override the configuration file

-
    -
  • HTTP port: 9200 and successors
  • -
  • Transport : 9300 (internal communications)
  • -
-

Discovery

-
    -
  • AWS plugin available --> also include integration with S3 (snapshot to S3)
  • -
  • AWS: multi-AZ is OK but replication across far data centers is not recommended
  • -
  • See: resiliency
  • -
-

Sites plugins -- kopf / head / paramedic / bigdesk / kibana -- contain static web content (JS, HTML....)

-

Install plugins on ALL machines of the cluster

-

To install,

-
  ./bin/plugin install marvel-agent
-  ./bin/plugin remove marvel-agent
-
- -

One type per index is recommended, except for parent child / nested indexes.

-

index size optimization: -- can disable _source and _all (the index that captures every field - not needed unless the top search bar changes) -- by default, Kibana will search _all

-

data types: -string, number, bool, datetime, binary, array, object, geo_point, geo_shape, ip, multifield -binary should be base64 encoded before storage

-

MAINTENANCE

-

Steps to restore elastic search data:

-
    -
  1. Stop elastic search
  2. -
  3. Extract the zip file (dump file)
  4. -
  5. Start elastic search
  6. -
  7. Reload elastic search
  8. -
-

The commands to do the above are as below:

-
    -
  1. systemctl stop elasticsearch
  2. -
  3. extract gz file to destination path
  4. -
  5. systemctl start elasticsearch
  6. -
  7. systemctl daemon-reload elasticsearch
  8. -
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Search/Logstash.md b/docs/Search/Logstash.md similarity index 72% rename from docs_src/Search/Logstash.md rename to docs/Search/Logstash.md index c3253db..a8791c7 100644 --- a/docs_src/Search/Logstash.md +++ b/docs/Search/Logstash.md @@ -6,39 +6,38 @@ Use ``path.data`` to distribute the data on multiple (EBS) disks - ## Outputs - MongoDB - PagerDuty - Nagios -- Graphite -- Ganglia +- Graphite +- Ganglia - StatsD - Redis - RabbitMQ -``` +```txt output { - elasticsearch { } # http://localhost:9200 + elasticsearch { } # https://localhost:9200 } ``` -``` +```txt output { redis { host => "redis.example.com" - data_type =>: "list" - + data_type =>: "list" + } } ``` ### Output to file -``` +```txt output { - file { + file { } } @@ -48,29 +47,29 @@ output { Use "date" for normalizing dates: -``` +```txt filter { date{ timezone => "America/Los_Angeles" locale => "en" # English - + } - geoip { - + geoip { + source => "clientip" # will read from clientip field - database => ... # use MaxMind's GeoLiteCity by default + database => ... # use MaxMind's GeoLiteCity by default } useragent { - + } } ``` ### Mutate a field -``` -filter { - if [action] == "login { +```txt +filter { + if [action] == "login { mutate { remove_field => "secret" } } } @@ -78,22 +77,21 @@ filter { ### Conditionals both in ``filter`` and ``outputs`` -``` -regexp -=~ +```txt +regexp +=~ !~ ``` -``` -output { - if [loglevel] == "ERROR" +```txt +output { + if [loglevel] == "ERROR" } ``` ## Interesting Plugins -[Stanford NLP library logstash plugin]( +[Stanford NLP library logstash plugin]( https://github.com/jwconway/logstash-filter-stanford-nlp ) - diff --git a/docs/Search/Logstash/index.html b/docs/Search/Logstash/index.html deleted file mode 100644 index 49a15bd..0000000 --- a/docs/Search/Logstash/index.html +++ /dev/null @@ -1,2144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - LogStash - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

LogStash

-

Operations

-

logstash -w 4 to set the number of worker threads

-

Use path.data to distribute the data on multiple (EBS) disks

-

Outputs

-
    -
  • MongoDB
  • -
  • PagerDuty
  • -
  • Nagios
  • -
  • Graphite
  • -
  • Ganglia
  • -
  • StatsD
  • -
  • Redis
  • -
  • RabbitMQ
  • -
-
output {
-     elasticsearch { }   # http://localhost:9200
-}
-
- -
output {
-     redis {
-          host => "redis.example.com"
-          data_type =>: "list" 
-
-     }
-}
-
- -

Output to file

-
output {
-      file { 
-
-     }
-}
-
- -

Filtering

-

Use "date" for normalizing dates:

-
filter {
-     date{
-         timezone => "America/Los_Angeles"
-         locale => "en"      # English
-
-     }
-     geoip { 
-
-         source => "clientip"   # will read from clientip field
-          database =>  ... # use MaxMind's GeoLiteCity by default 
-     }
-     useragent {
-
-     }
-}
-
- -

Mutate a field

-
filter { 
-     if [action] == "login { 
-          mutate { remove_field => "secret" }
-     }
-}
-
- -

Conditionals both in filter and outputs

-
regexp 
-=~  
-!~
-
- -
output { 
-     if [loglevel] == "ERROR" 
-
-}
-
- -

Interesting Plugins

-

Stanford NLP library logstash plugin

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/Search/search_index.json b/docs/Search/search_index.json deleted file mode 100644 index e826bcf..0000000 --- a/docs/Search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"You will find here a collection of cheatsheets, code templates and snippets that I have collected over the years... Given that they were created for my own use, these notes are often very terse and dense. Thank you for your patience, while I am slowly improving their readability. I also have hundreds more to move to GitHub Pages :-) In the meanwhile, feel free to use as you wish. Please email me suggestions and corrections.","title":"Home"},{"location":"Big_Data/Hadoop_Ecosystem/","text":"Hadoop Ecosystem \u00b6 Hadoop is not a single product, but rather a software family. Its common components consist of the following: Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources Hive, used to facilitate structure for the data HCatalog, used to provide inter-operatability between these internal systems HBase, which is essentially a database built on top of Hadoop HDFS, the actual file system for hadoop. Apache Mahout Packaging for Hadoop: BigTop Hadoop structures data using Hive, but can handle unstructured data easily using Pig. Hadoop and Mongo \u00b6 Hadoop and MongoDB Hadoop and MongoDB Use Cases AWS EMR \u00b6 Amazon EMR Best Practices Amazon EMR includes Ganglia Hadoop HBase HCatalog Hive Hue Mahout Oozie Phoenix Pig Prest0 Spark Sqoop Tez Zeppelin ZooKeeper","title":"Hadoop Ecosystem"},{"location":"Big_Data/Hadoop_Ecosystem/#hadoop-ecosystem","text":"Hadoop is not a single product, but rather a software family. Its common components consist of the following: Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources Hive, used to facilitate structure for the data HCatalog, used to provide inter-operatability between these internal systems HBase, which is essentially a database built on top of Hadoop HDFS, the actual file system for hadoop. Apache Mahout Packaging for Hadoop: BigTop Hadoop structures data using Hive, but can handle unstructured data easily using Pig.","title":"Hadoop Ecosystem"},{"location":"Big_Data/Hadoop_Ecosystem/#hadoop-and-mongo","text":"Hadoop and MongoDB Hadoop and MongoDB Use Cases","title":"Hadoop and Mongo"},{"location":"Big_Data/Hadoop_Ecosystem/#aws-emr","text":"Amazon EMR Best Practices Amazon EMR includes Ganglia Hadoop HBase HCatalog Hive Hue Mahout Oozie Phoenix Pig Prest0 Spark Sqoop Tez Zeppelin ZooKeeper","title":"AWS EMR"},{"location":"Big_Data/Install_Spark_2.3_Locally/","text":"Install Spark 2.3 Locally \u00b6 Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11. Download Spark \u00b6 Link Java \u00b6 All you need is to have java installed on your system PATH, or the JAVA_HOME environment variable pointing to a Java installation. java -version Scala \u00b6 Download the Scala binaries for windows -- you will need Scala 11.x (not 10.x or 12.x) for Spark 2.3 Latest Scala Scala version 2.11.12 Test correct installation of scala: scala -version Set PATH for Scala if needed: export PATH = $PATH :/usr/local/scala/bin Test that Spark is properly installed: ./bin/spark-shell --master local [ 2 ] On Windows, use CMD or PowerShell, not git bash Error: Failure to locate the winutils binary in the hadoop binary path \u00b6 HADOOP_HOME (or the variable hadoop.home.dir property) needs to be set properly. Known Hadoop for Windows issue: winutils is not included in the Apache distribution You can fix this problem in two ways Install a full native windows Hadoop version. The ASF does not currently release such a version; releases are available externally. Or: get the WINUTILS.EXE binary from a Hadoop redistribution. There is a repository of this for some Hadoop versions on github. Then Set the environment variable %HADOOP_HOME% to point to the directory above the BIN dir containing WINUTILS.EXE. Or: run the Java process with the system property hadoop.home.dir set to the home directory. Explanation on Hadoop Wiki Stack Overflow Windows binaries for some Hadoop versions Run Spark on the local machine \u00b6 To run Spark interactively in a Python interpreter, use bin/pyspark : ./bin/pyspark --master local [ 2 ] Or submit Spark jobs: ./bin/spark-submit examples/src/main/python/pi.py 10 Additional Links \u00b6 Spark Installation Tutorial","title":"Install Spark 2.3 Locally"},{"location":"Big_Data/Install_Spark_2.3_Locally/#install-spark-23-locally","text":"Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11.","title":"Install Spark 2.3 Locally"},{"location":"Big_Data/Install_Spark_2.3_Locally/#download-spark","text":"Link","title":"Download Spark"},{"location":"Big_Data/Install_Spark_2.3_Locally/#java","text":"All you need is to have java installed on your system PATH, or the JAVA_HOME environment variable pointing to a Java installation. java -version","title":"Java"},{"location":"Big_Data/Install_Spark_2.3_Locally/#scala","text":"Download the Scala binaries for windows -- you will need Scala 11.x (not 10.x or 12.x) for Spark 2.3 Latest Scala Scala version 2.11.12 Test correct installation of scala: scala -version Set PATH for Scala if needed: export PATH = $PATH :/usr/local/scala/bin Test that Spark is properly installed: ./bin/spark-shell --master local [ 2 ] On Windows, use CMD or PowerShell, not git bash","title":"Scala"},{"location":"Big_Data/Install_Spark_2.3_Locally/#error-failure-to-locate-the-winutils-binary-in-the-hadoop-binary-path","text":"HADOOP_HOME (or the variable hadoop.home.dir property) needs to be set properly. Known Hadoop for Windows issue: winutils is not included in the Apache distribution You can fix this problem in two ways Install a full native windows Hadoop version. The ASF does not currently release such a version; releases are available externally. Or: get the WINUTILS.EXE binary from a Hadoop redistribution. There is a repository of this for some Hadoop versions on github. Then Set the environment variable %HADOOP_HOME% to point to the directory above the BIN dir containing WINUTILS.EXE. Or: run the Java process with the system property hadoop.home.dir set to the home directory. Explanation on Hadoop Wiki Stack Overflow Windows binaries for some Hadoop versions","title":"Error: Failure to locate the winutils binary in the hadoop binary path"},{"location":"Big_Data/Install_Spark_2.3_Locally/#run-spark-on-the-local-machine","text":"To run Spark interactively in a Python interpreter, use bin/pyspark : ./bin/pyspark --master local [ 2 ] Or submit Spark jobs: ./bin/spark-submit examples/src/main/python/pi.py 10","title":"Run Spark on the local machine"},{"location":"Big_Data/Install_Spark_2.3_Locally/#additional-links","text":"Spark Installation Tutorial","title":"Additional Links"},{"location":"Big_Data/Spark_APIs/","text":"DataFrames APIs \u00b6 DataFrame operations: printSchema() select() show() count() groupBy() sum() limit() orderBy() filter() withColumnRenamed() join() withColumn() Example: // In the Regular Expression below: // ^ - Matches beginning of line // .* - Matches any characters, except newline df . filter ( $ \"article\" . rlike ( \"\"\"^Apache_.*\"\"\" )) . orderBy ( $ \"requests\" . desc ) . show () // By default, show will return 20 rows // Import the sql functions package, which includes statistical functions like sum, max, min, avg, etc. import org.apache.spark.sql.functions._ df . groupBy ( \"project\" ). sum (). show () Columns \u00b6 A new column is constructed based on the input columns present in a dataframe: df ( \"columnName\" ) // On a specific DataFrame. col ( \"columnName\" ) // A generic column no yet associated with a DataFrame. col ( \"columnName.field\" ) // Extracting a struct field col ( \"`a.column.with.dots`\" ) // Escape `.` in column names. $ \"columnName\" // Scala short hand for a named column. expr ( \"a + 1\" ) // A column that is constructed from a parsed SQL Expression. lit ( \"abc\" ) // A column that produces a literal (constant) value. Column objects can be composed to form complex expressions: $ \"a\" + 1 $ \"a\" === $ \"b\" File Read \u00b6 CSV - Create a DataFrame with the anticipated structure val clickstreamDF = sqlContext . read . format ( \"com.databricks.spark.csv\" ) . option ( \"header\" , \"true\" ) . option ( \"delimiter\" , \"\\\\t\" ) . option ( \"mode\" , \"PERMISSIVE\" ) . option ( \"inferSchema\" , \"true\" ) . load ( \"dbfs:///databricks-datasets/wikipedia-datasets/data-001/clickstream/raw-uncompressed\" ) PARQUET - To create Dataset[Row] using SparkSession val people = spark . read . parquet ( \"...\" ) val department = spark . read . parquet ( \"...\" ) people . filter ( \"age > 30\" ) . join ( department , people ( \"deptId\" ) === department ( \"id\" )) . groupBy ( department ( \"name\" ), \"gender\" ) . agg ( avg ( people ( \"salary\" )), max ( people ( \"age\" ))) Repartitioning / Caching \u00b6 val clickstreamNoIDs8partDF = clickstreamNoIDsDF . repartition ( 8 ) clickstreamNoIDs8partDF . registerTempTable ( \"Clickstream\" ) sqlContext . cacheTable ( \"Clickstream\" ) An ideal partition size in Spark is about 50 MB - 200 MB. The cache gets stored in Project Tungsten binary compressed columnar format.","title":"Spark APIs"},{"location":"Big_Data/Spark_APIs/#dataframes-apis","text":"DataFrame operations: printSchema() select() show() count() groupBy() sum() limit() orderBy() filter() withColumnRenamed() join() withColumn() Example: // In the Regular Expression below: // ^ - Matches beginning of line // .* - Matches any characters, except newline df . filter ( $ \"article\" . rlike ( \"\"\"^Apache_.*\"\"\" )) . orderBy ( $ \"requests\" . desc ) . show () // By default, show will return 20 rows // Import the sql functions package, which includes statistical functions like sum, max, min, avg, etc. import org.apache.spark.sql.functions._ df . groupBy ( \"project\" ). sum (). show ()","title":"DataFrames APIs"},{"location":"Big_Data/Spark_APIs/#columns","text":"A new column is constructed based on the input columns present in a dataframe: df ( \"columnName\" ) // On a specific DataFrame. col ( \"columnName\" ) // A generic column no yet associated with a DataFrame. col ( \"columnName.field\" ) // Extracting a struct field col ( \"`a.column.with.dots`\" ) // Escape `.` in column names. $ \"columnName\" // Scala short hand for a named column. expr ( \"a + 1\" ) // A column that is constructed from a parsed SQL Expression. lit ( \"abc\" ) // A column that produces a literal (constant) value. Column objects can be composed to form complex expressions: $ \"a\" + 1 $ \"a\" === $ \"b\"","title":"Columns"},{"location":"Big_Data/Spark_APIs/#file-read","text":"CSV - Create a DataFrame with the anticipated structure val clickstreamDF = sqlContext . read . format ( \"com.databricks.spark.csv\" ) . option ( \"header\" , \"true\" ) . option ( \"delimiter\" , \"\\\\t\" ) . option ( \"mode\" , \"PERMISSIVE\" ) . option ( \"inferSchema\" , \"true\" ) . load ( \"dbfs:///databricks-datasets/wikipedia-datasets/data-001/clickstream/raw-uncompressed\" ) PARQUET - To create Dataset[Row] using SparkSession val people = spark . read . parquet ( \"...\" ) val department = spark . read . parquet ( \"...\" ) people . filter ( \"age > 30\" ) . join ( department , people ( \"deptId\" ) === department ( \"id\" )) . groupBy ( department ( \"name\" ), \"gender\" ) . agg ( avg ( people ( \"salary\" )), max ( people ( \"age\" )))","title":"File Read"},{"location":"Big_Data/Spark_APIs/#repartitioning--caching","text":"val clickstreamNoIDs8partDF = clickstreamNoIDsDF . repartition ( 8 ) clickstreamNoIDs8partDF . registerTempTable ( \"Clickstream\" ) sqlContext . cacheTable ( \"Clickstream\" ) An ideal partition size in Spark is about 50 MB - 200 MB. The cache gets stored in Project Tungsten binary compressed columnar format.","title":"Repartitioning / Caching"},{"location":"Big_Data/Spark_Basics/","text":"Spark Basics \u00b6 Main Web Site Apache Spark on Wikipedia Useful Links \u00b6 Ampcamp big data bootcamp RDDs Simplified Elasticsearch and Apache Lucene for Apache Spark and MLlib Spark on AWS Running Apache Spark on AWS Running Apache Spark EMR and EC2 scripts on AWS with read write S3 Spark on EMR - How to Submit a Spark Application with EMR Steps Databricks Reference Apps Introduction to Apache Spark with Examples and Use Cases Spark and MongoDB \u00b6 Using MongoDB with Apache Spark MongoDB Spark connector Spark and NLP \u00b6 Dictionary Based Annotation at Scale with Spark, SolrTextTagger and OpenNLP Here is a complete set of example on how to use DL4J (Deep Learning for Java) that uses UIMA on the SPARK platform Deep Learning for Java and in the following project the use of CTAKES UIMA module from within the Spark framework Natural Language Processing with Apache Spark GraphX \u00b6 Graphx programming guide Apache Zeppelin \u00b6 Connect to Zeppelin using the same SSH tunneling method to connect to other web servers on the master node. Zeppelin server is found at port 8890. Zeppelin","title":"Spark Basics"},{"location":"Big_Data/Spark_Basics/#spark-basics","text":"Main Web Site Apache Spark on Wikipedia","title":"Spark Basics"},{"location":"Big_Data/Spark_Basics/#useful-links","text":"Ampcamp big data bootcamp RDDs Simplified Elasticsearch and Apache Lucene for Apache Spark and MLlib Spark on AWS Running Apache Spark on AWS Running Apache Spark EMR and EC2 scripts on AWS with read write S3 Spark on EMR - How to Submit a Spark Application with EMR Steps Databricks Reference Apps Introduction to Apache Spark with Examples and Use Cases","title":"Useful Links"},{"location":"Big_Data/Spark_Basics/#spark-and-mongodb","text":"Using MongoDB with Apache Spark MongoDB Spark connector","title":"Spark and MongoDB"},{"location":"Big_Data/Spark_Basics/#spark-and-nlp","text":"Dictionary Based Annotation at Scale with Spark, SolrTextTagger and OpenNLP Here is a complete set of example on how to use DL4J (Deep Learning for Java) that uses UIMA on the SPARK platform Deep Learning for Java and in the following project the use of CTAKES UIMA module from within the Spark framework Natural Language Processing with Apache Spark","title":"Spark and NLP"},{"location":"Big_Data/Spark_Basics/#graphx","text":"Graphx programming guide","title":"GraphX"},{"location":"Big_Data/Spark_Basics/#apache-zeppelin","text":"Connect to Zeppelin using the same SSH tunneling method to connect to other web servers on the master node. Zeppelin server is found at port 8890. Zeppelin","title":"Apache Zeppelin"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/","text":"Setup a Spark Development Environment with IntelliJ and sbt \u00b6 Useful Links \u00b6 Hortonworks tutorial Packaging and Submission Steps using sbt \u00b6 Package a jar containing your application: $ sbt package ... [ info ] Packaging { .. } / { .. } /target/scala-2.11/simple-project_2.11-1.0.jar Don't use sbt run Then use [spark submit] ( https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit ) to run your application YOUR_SPARK_HOME/bin/spark-submit \\ --class \"SimpleApp\" \\ --master local [ 4 ] \\ target/scala-2.11/simple-project_2.11-1.0.jar Open the Spark UI to monitor: http://localhost:4040 Plugins \u00b6 sbt-spark-package \u00b6 The Sbt Plugin for Spark Packages is a Sbt plugin that aims to simplify the use and development of Spark Packages. Blog IntelliJ plugin for Spark \u00b6 Note: does not work with IntelliJ 2018.1 The IntelliJ plugin for Spark supports for deployment spark application and cluster monitoring. To install, download the plugin File > Settings, Plugins tab, browse repos... point to the zip file","title":"Setup a Spark Development Environment with IntelliJ and sbt"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#setup-a-spark-development-environment-with-intellij-and-sbt","text":"","title":"Setup a Spark Development Environment with IntelliJ and sbt"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#useful-links","text":"Hortonworks tutorial","title":"Useful Links"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#packaging-and-submission-steps-using-sbt","text":"Package a jar containing your application: $ sbt package ... [ info ] Packaging { .. } / { .. } /target/scala-2.11/simple-project_2.11-1.0.jar Don't use sbt run Then use [spark submit] ( https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit ) to run your application YOUR_SPARK_HOME/bin/spark-submit \\ --class \"SimpleApp\" \\ --master local [ 4 ] \\ target/scala-2.11/simple-project_2.11-1.0.jar Open the Spark UI to monitor: http://localhost:4040","title":"Packaging and Submission Steps using sbt"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#plugins","text":"","title":"Plugins"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#sbt-spark-package","text":"The Sbt Plugin for Spark Packages is a Sbt plugin that aims to simplify the use and development of Spark Packages. Blog","title":"sbt-spark-package"},{"location":"Big_Data/Spark_Development_with_sbt_and_InteliJ/#intellij-plugin-for-spark","text":"Note: does not work with IntelliJ 2018.1 The IntelliJ plugin for Spark supports for deployment spark application and cluster monitoring. To install, download the plugin File > Settings, Plugins tab, browse repos... point to the zip file","title":"IntelliJ plugin for Spark"},{"location":"Big_Data/Spark_on_AWS_EMR/","text":"Spark on AWS EMR \u00b6 Key Links \u00b6 Spark on AWS EMR Create a EMR Cluster with Spark using the AWS Console \u00b6 The following procedure creates a cluster with Spark installed. Open the Amazon EMR console at https://console.aws.amazon.com/elasticmapreduce/ . Choose Create cluster to use Quick Create. For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later. In the Select Applications field, choose either All Applications or Spark. Select other options as necessary and then choose Create cluster Create a EMR Cluster with Spark using the AWS CLI \u00b6 Simple cluster: aws emr create-cluster --name \"Spark cluster\" --release-label emr-5.0.0 --applications Name = Spark \\ --ec2-attributes KeyName = myKey --instance-type m3.xlarge --instance-count 3 --use-default-roles Note: For Windows, replace the above Linux line continuation character () with the caret (^). When using a config file: aws emr create-cluster --release-label --applications Name = Spark \\ --instance-type m3.xlarge --instance-count 3 --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json Sample myConfig.json: [ { \"Classification\" : \"spark\" , \"Properties\" : { \"maximizeResourceAllocation\" : \"true\" } } ] Using Spot instances: aws emr create-cluster --name \"Spot cluster\" --release-label emr-5.0.0 --applications Name = Spark \\ --use-default-roles --ec2-attributes KeyName = myKey \\ --instance-groups InstanceGroupType = MASTER,InstanceType = m3.xlarge,InstanceCount = 1 ,BidPrice = 0 .25 \\ InstanceGroupType = CORE,BidPrice = 0 .03,InstanceType = m3.xlarge,InstanceCount = 2 # InstanceGroupType=TASK,BidPrice=0.10,InstanceType=m3.xlarge,InstanceCount=3 In Java: // start Spark on EMR in java AmazonElasticMapReduceClient emr = new AmazonElasticMapReduceClient ( credentials ); Application sparkApp = new Application () . withName ( \"Spark\" ); Applications myApps = new Applications (); myApps . add ( sparkApp ); RunJobFlowRequest request = new RunJobFlowRequest () . withName ( \"Spark Cluster\" ) . withApplications ( myApps ) . withReleaseLabel ( \"\" ) . withInstances ( new JobFlowInstancesConfig () . withEc2KeyName ( \"myKeyName\" ) . withInstanceCount ( 1 ) . withKeepJobFlowAliveWhenNoSteps ( true ) . withMasterInstanceType ( \"m3.xlarge\" ) . withSlaveInstanceType ( \"m3.xlarge\" ) ); RunJobFlowResult result = emr . runJobFlow ( request ); Connect to the Master Node using SSH \u00b6 To connect to the master node using SSH, you need the public DNS name of the master node and your Amazon EC2 key pair private key. The Amazon EC2 key pair private key is specified when you launch the cluster. To retrieve the cluster identifier / the public DNS name of the master node, type the following command: aws emr list-clusters The output lists your clusters including the cluster IDs. Note the cluster ID for the cluster to which you are connecting. \"Status\" : { \"Timeline\" : { \"ReadyDateTime\" : 1408040782.374 , \"CreationDateTime\" : 1408040501.213 }, \"State\" : \"WAITING\" , \"StateChangeReason\" : { \"Message\" : \"Waiting after step completed\" } }, \"NormalizedInstanceHours\" : 4 , \"Id\" : \"j-2AL4XXXXXX5T9\" , \"Name\" : \"My cluster\" To list the cluster instances including the master public DNS name for the cluster, type one of the following commands. Replace j-2AL4XXXXXX5T9 with the cluster ID returned by the previous command. aws emr list-instances --cluster-id j-2AL4XXXXXX5T9Or:aws emr describe-clusters --cluster-id j-2AL4XXXXXX5T9 View the Web Interfaces Hosted on Amazon EMR Clusters \u00b6 View Web Interfaces Hosted on Amazon EMR Clusters YARN ResourceManager: http://master-public-dns-name:8088 YARN NodeManager: http://slave-public-dns-name:8042 Hadoop HDFS NameNode: http://master-public-dns-name:50070 Hadoop HDFS DataNode: http://slave-public-dns-name:50075 Spark HistoryServer: http://master-public-dns-name:18080 Zeppelin: http://master-public-dns-name:8890 Hue: http://master-public-dns-name:8888 Ganglia: http://master-public-dns-name/ganglia HBase UI: http://master-public-dns-name:16010","title":"Spark on AWS EMR"},{"location":"Big_Data/Spark_on_AWS_EMR/#spark-on-aws-emr","text":"","title":"Spark on AWS EMR"},{"location":"Big_Data/Spark_on_AWS_EMR/#key-links","text":"Spark on AWS EMR","title":"Key Links"},{"location":"Big_Data/Spark_on_AWS_EMR/#create-a-emr-cluster-with-spark-using-the-aws-console","text":"The following procedure creates a cluster with Spark installed. Open the Amazon EMR console at https://console.aws.amazon.com/elasticmapreduce/ . Choose Create cluster to use Quick Create. For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later. In the Select Applications field, choose either All Applications or Spark. Select other options as necessary and then choose Create cluster","title":"Create a EMR Cluster with Spark using the AWS Console"},{"location":"Big_Data/Spark_on_AWS_EMR/#create-a-emr-cluster-with-spark-using-the-aws-cli","text":"Simple cluster: aws emr create-cluster --name \"Spark cluster\" --release-label emr-5.0.0 --applications Name = Spark \\ --ec2-attributes KeyName = myKey --instance-type m3.xlarge --instance-count 3 --use-default-roles Note: For Windows, replace the above Linux line continuation character () with the caret (^). When using a config file: aws emr create-cluster --release-label --applications Name = Spark \\ --instance-type m3.xlarge --instance-count 3 --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json Sample myConfig.json: [ { \"Classification\" : \"spark\" , \"Properties\" : { \"maximizeResourceAllocation\" : \"true\" } } ] Using Spot instances: aws emr create-cluster --name \"Spot cluster\" --release-label emr-5.0.0 --applications Name = Spark \\ --use-default-roles --ec2-attributes KeyName = myKey \\ --instance-groups InstanceGroupType = MASTER,InstanceType = m3.xlarge,InstanceCount = 1 ,BidPrice = 0 .25 \\ InstanceGroupType = CORE,BidPrice = 0 .03,InstanceType = m3.xlarge,InstanceCount = 2 # InstanceGroupType=TASK,BidPrice=0.10,InstanceType=m3.xlarge,InstanceCount=3 In Java: // start Spark on EMR in java AmazonElasticMapReduceClient emr = new AmazonElasticMapReduceClient ( credentials ); Application sparkApp = new Application () . withName ( \"Spark\" ); Applications myApps = new Applications (); myApps . add ( sparkApp ); RunJobFlowRequest request = new RunJobFlowRequest () . withName ( \"Spark Cluster\" ) . withApplications ( myApps ) . withReleaseLabel ( \"\" ) . withInstances ( new JobFlowInstancesConfig () . withEc2KeyName ( \"myKeyName\" ) . withInstanceCount ( 1 ) . withKeepJobFlowAliveWhenNoSteps ( true ) . withMasterInstanceType ( \"m3.xlarge\" ) . withSlaveInstanceType ( \"m3.xlarge\" ) ); RunJobFlowResult result = emr . runJobFlow ( request );","title":"Create a EMR Cluster with Spark using the AWS CLI"},{"location":"Big_Data/Spark_on_AWS_EMR/#connect-to-the-master-node-using-ssh","text":"To connect to the master node using SSH, you need the public DNS name of the master node and your Amazon EC2 key pair private key. The Amazon EC2 key pair private key is specified when you launch the cluster. To retrieve the cluster identifier / the public DNS name of the master node, type the following command: aws emr list-clusters The output lists your clusters including the cluster IDs. Note the cluster ID for the cluster to which you are connecting. \"Status\" : { \"Timeline\" : { \"ReadyDateTime\" : 1408040782.374 , \"CreationDateTime\" : 1408040501.213 }, \"State\" : \"WAITING\" , \"StateChangeReason\" : { \"Message\" : \"Waiting after step completed\" } }, \"NormalizedInstanceHours\" : 4 , \"Id\" : \"j-2AL4XXXXXX5T9\" , \"Name\" : \"My cluster\" To list the cluster instances including the master public DNS name for the cluster, type one of the following commands. Replace j-2AL4XXXXXX5T9 with the cluster ID returned by the previous command. aws emr list-instances --cluster-id j-2AL4XXXXXX5T9Or:aws emr describe-clusters --cluster-id j-2AL4XXXXXX5T9","title":"Connect to the Master Node using SSH"},{"location":"Big_Data/Spark_on_AWS_EMR/#view-the-web-interfaces-hosted-on-amazon-emr-clusters","text":"View Web Interfaces Hosted on Amazon EMR Clusters YARN ResourceManager: http://master-public-dns-name:8088 YARN NodeManager: http://slave-public-dns-name:8042 Hadoop HDFS NameNode: http://master-public-dns-name:50070 Hadoop HDFS DataNode: http://slave-public-dns-name:50075 Spark HistoryServer: http://master-public-dns-name:18080 Zeppelin: http://master-public-dns-name:8890 Hue: http://master-public-dns-name:8888 Ganglia: http://master-public-dns-name/ganglia HBase UI: http://master-public-dns-name:16010","title":"View the Web Interfaces Hosted on Amazon EMR Clusters"},{"location":"Big_Data/Spark_on_EC2/","text":"Install Spark on EC2 with Flintrock \u00b6 Key Links \u00b6 Flintrock GitHub Repo Configurable CLI Defaults \u00b6 Flintrock lets you persist your desired configuration to a YAML file so that you don't have to keep typing out the same options over and over at the command line. To setup and edit the default config file, run this: flintrock configure Sample config.yaml \u00b6 provider : ec2 services : spark : version : 2.2.0 launch : num-slaves : 1 providers : ec2 : key-name : key_name identity-file : /path/to/.ssh/key.pem instance-type : m3.medium region : us-east-1 ami : ami-97785bed user : ec2-user With a config file like that, you can now launch a cluster: flintrock launch test-cluster","title":"Install Spark on EC2 with Flintrock"},{"location":"Big_Data/Spark_on_EC2/#install-spark-on-ec2-with-flintrock","text":"","title":"Install Spark on EC2 with Flintrock"},{"location":"Big_Data/Spark_on_EC2/#key-links","text":"Flintrock GitHub Repo","title":"Key Links"},{"location":"Big_Data/Spark_on_EC2/#configurable-cli-defaults","text":"Flintrock lets you persist your desired configuration to a YAML file so that you don't have to keep typing out the same options over and over at the command line. To setup and edit the default config file, run this: flintrock configure","title":"Configurable CLI Defaults"},{"location":"Big_Data/Spark_on_EC2/#sample-configyaml","text":"provider : ec2 services : spark : version : 2.2.0 launch : num-slaves : 1 providers : ec2 : key-name : key_name identity-file : /path/to/.ssh/key.pem instance-type : m3.medium region : us-east-1 ami : ami-97785bed user : ec2-user With a config file like that, you can now launch a cluster: flintrock launch test-cluster","title":"Sample config.yaml"},{"location":"Big_Data/Spark_on_Kubernetes/","text":"Background \u00b6 Introduction to Spark on Kubernetes Running Spark on Kubernetes \u00b6 Main Page Prerequisites: A runnable distribution of Spark 2.3 or above. A running Kubernetes cluster at version >= 1.6 with access configured to it using kubectl. If you do not already have a working Kubernetes cluster, you may setup a test cluster on your local machine using minikube. We recommend using the latest release of minikube with the DNS addon enabled. Be aware that the default minikube configuration is not enough for running Spark applications. We recommend 3 CPUs and 4g of memory to be able to start a simple Spark application with a single executor. You must have appropriate permissions to list, create, edit and delete pods in your cluster. You can verify that you can list these resources by running kubectl auth can-i pods. The service account credentials used by the driver pods must be allowed to create pods, services and configmaps. You must have Kubernetes DNS configured in your cluster. Steps \u00b6 Need Kubernetes version 1.6 and above. To check the version, enter kubectl version . The cluster must be configured to use the kube-dns addon. Check with minikube addons list Kubernetes DNS Page Start minikube with the recommended configuration for Spark minikube start --cpus 3 --memory 4096 Submit a Spark job using: $ bin/spark-submit \\ --master k8s://https://: \\ --deploy-mode cluster \\ --name spark-pi \\ --class org.apache.spark.examples.SparkPi \\ --conf spark.executor.instances = 3 \\ --conf spark.kubernetes.container.image = \\ local:///path/to/examples.jar Use kubectl cluster-info to get the K8s API server URL Spark (starting with version 2.3) ships with a Dockerfile in the kubernetes/dockerfiles/ directory. Access logs: $ kubectl -n = logs -f Accessing Driver UI: $ kubectl port-forward 4040 :4040 Then go to http://localhost:4040 Alternatives \u00b6 Helm Chart for Spark The same on KubeApps helm install --name my-spark-release --version 0 .1.12 stable/spark","title":"Spark 2.3 on Kubernetes"},{"location":"Big_Data/Spark_on_Kubernetes/#background","text":"Introduction to Spark on Kubernetes","title":"Background"},{"location":"Big_Data/Spark_on_Kubernetes/#running-spark-on-kubernetes","text":"Main Page Prerequisites: A runnable distribution of Spark 2.3 or above. A running Kubernetes cluster at version >= 1.6 with access configured to it using kubectl. If you do not already have a working Kubernetes cluster, you may setup a test cluster on your local machine using minikube. We recommend using the latest release of minikube with the DNS addon enabled. Be aware that the default minikube configuration is not enough for running Spark applications. We recommend 3 CPUs and 4g of memory to be able to start a simple Spark application with a single executor. You must have appropriate permissions to list, create, edit and delete pods in your cluster. You can verify that you can list these resources by running kubectl auth can-i pods. The service account credentials used by the driver pods must be allowed to create pods, services and configmaps. You must have Kubernetes DNS configured in your cluster.","title":"Running Spark on Kubernetes"},{"location":"Big_Data/Spark_on_Kubernetes/#steps","text":"Need Kubernetes version 1.6 and above. To check the version, enter kubectl version . The cluster must be configured to use the kube-dns addon. Check with minikube addons list Kubernetes DNS Page Start minikube with the recommended configuration for Spark minikube start --cpus 3 --memory 4096 Submit a Spark job using: $ bin/spark-submit \\ --master k8s://https://: \\ --deploy-mode cluster \\ --name spark-pi \\ --class org.apache.spark.examples.SparkPi \\ --conf spark.executor.instances = 3 \\ --conf spark.kubernetes.container.image = \\ local:///path/to/examples.jar Use kubectl cluster-info to get the K8s API server URL Spark (starting with version 2.3) ships with a Dockerfile in the kubernetes/dockerfiles/ directory. Access logs: $ kubectl -n = logs -f Accessing Driver UI: $ kubectl port-forward 4040 :4040 Then go to http://localhost:4040","title":"Steps"},{"location":"Big_Data/Spark_on_Kubernetes/#alternatives","text":"Helm Chart for Spark The same on KubeApps helm install --name my-spark-release --version 0 .1.12 stable/spark","title":"Alternatives"},{"location":"Cloud/AWS/","text":"AWS Services Overview \u00b6 Basic Services \u00b6 Compute: EC2 (autoscaling, ELB load balancing) Networking / Security: VPC (security groups), IAM (users/groups/application roles) Storage \u00b6 S3: secure, scalable object-level storage, static web site hosting... Glacier: long-term storage EBS: block-level storage (for EC2 instances) Databases \u00b6 RDS: relational databases (MySQL, PostgreSQL, MSSQL, MariaDB, Aurora...) DynamoDB: scalable NoSQL database backed by solid-state drives Analytics \u00b6 RedShift: PostgreSQL-based columnstore OLAP database that uses SQL. MPP architecture. EMR: Hadoop cluster (Hive, Pig, HBase, Spark...). ETL / ELT / Batch Processing \u00b6 Glue Batch Data Pipeline: orchestrate data transfers between S3, DynamoDB, Redshift Application Services \u00b6 Notifications: SNS (alerts by email, SMS...), SES (bulk email) Queue: SQS (async message queues for component decoupling) Workflows, State Machine as a Service: AWS Step Functions, SWF (task-oriented workflows - complicated) Document Search: ElasticSearch, CloudSearch Monitoring \u00b6 Cloudwatch (monitor services and instances e.g. CPU utilization, etc...) CloudTrail (monitor API calls) Infrastructure Deployment / Automation \u00b6 Elastic Beanstalk (simple, mostly web or Linux worker) CloudFormation (JSON / YAML templates - more difficult, but many existing templates) OpsWork (higher level than CloudFormation, uses non-native components - Chef-based) Desktop in the Cloud \u00b6 WorkSpaces Details \u00b6 Tools \u00b6 Unix tools on Windows: Cygwin Putty SSH client for Windows doc Download and install PuTTY link . Be sure to install the entire suite. Start PuTTYgen (for example, from the Start menu, click All Programs > PuTTY > PuTTYgen). Under Type of key to generate, select SSH-2 RSA. Load the .pem file (private key) downloaded from the console (in \"credentials\" folder) Save private key AWS command line interface AWS toolkit for Visual Studio AWS tools for PowerShell AWS EC2 \u00b6 Log onto instance with Putty SSH login as: ec2-user (Amazon Linux) or: ubuntu Bash shell documentation Use a shell script to configure the instance link User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the \"As file\" option and browse for the file to attach. AWS S3 \u00b6 GUI tools to upload / manage files: AWS Console S3 Browser CloudBerry Command-line s3 clients: AWS command line (see above) S3 command line tools Redshift \u00b6 1) Use Case Large-scale SQL analytical database Querying in Redshift is FAST Full SQL compared to HiveQL Redshift isn\u2019t a complete replacement for a Hadoop system (no streaming, no text processing) 2) Tools install SQL tool or Aginity Microsoft SSDT 3) Get data into Redshift: COPY from S3 (delimited text files) COPY from DynamoDB (NoSQL datastore) JDBC/ODBC transactions (not efficient for bulk loading) Tables have \u2018keys\u2019 that define how the data is split across slices. The recommended practice is to split based upon commonly-joined columns, so that joined data resides on the same slice, thus avoiding the need to move data between systems. 4) Examples: COPY table1 FROM 's3://bucket1/' credentials 'aws_access_key_id=abc;aws_secret_access_key=xyz' delimiter '|' gzip removequotes truncatecolumns maxerror 1000 SELECT DISTINCT field1 FROM table1 SELECT COUNT ( DISTINCT field2 ) FROM table1 EMR \u00b6 EMR FAQs Extract, Transform, and Load (ETL) Data with Amazon EMR EMR article SWF \u00b6 The Amazon Simple Workflow Service (Amazon SWF) makes it easy to build applications that coordinate work across distributed components. In Amazon SWF, a task represents a logical unit of work that is performed by a component of your application. Coordinating tasks across the application involves managing intertask dependencies, scheduling, and concurrency in accordance with the logical flow of the application. Amazon SWF gives you full control over implementing tasks and coordinating them without worrying about underlying complexities such as tracking their progress and maintaining their state. When using Amazon SWF, you implement workers to perform tasks. These workers can run either on cloud infrastructure, such as Amazon Elastic Compute Cloud (Amazon EC2), or on your own premises. You can create tasks that are long-running, or that may fail, time out, or require restarts\u2014or that may complete with varying throughput and latency. Amazon SWF stores tasks and assigns them to workers when they are ready, tracks their progress, and maintains their state, including details on their completion. To coordinate tasks, you write a program that gets the latest state of each task from Amazon SWF and uses it to initiate subsequent tasks. Amazon SWF maintains an application's execution state durably so that the application is resilient to failures in individual components. With Amazon SWF, you can implement, deploy, scale, and modify these application components independently. Amazon SWF offers capabilities to support a variety of application requirements. It is suitable for a range of use cases that require coordination of tasks, including media processing, web application back-ends, business process workflows, and analytics pipelines.","title":"AWS Services Overview"},{"location":"Cloud/AWS/#aws-services-overview","text":"","title":"AWS Services Overview"},{"location":"Cloud/AWS/#basic-services","text":"Compute: EC2 (autoscaling, ELB load balancing) Networking / Security: VPC (security groups), IAM (users/groups/application roles)","title":"Basic Services"},{"location":"Cloud/AWS/#storage","text":"S3: secure, scalable object-level storage, static web site hosting... Glacier: long-term storage EBS: block-level storage (for EC2 instances)","title":"Storage"},{"location":"Cloud/AWS/#databases","text":"RDS: relational databases (MySQL, PostgreSQL, MSSQL, MariaDB, Aurora...) DynamoDB: scalable NoSQL database backed by solid-state drives","title":"Databases"},{"location":"Cloud/AWS/#analytics","text":"RedShift: PostgreSQL-based columnstore OLAP database that uses SQL. MPP architecture. EMR: Hadoop cluster (Hive, Pig, HBase, Spark...).","title":"Analytics"},{"location":"Cloud/AWS/#etl--elt--batch-processing","text":"Glue Batch Data Pipeline: orchestrate data transfers between S3, DynamoDB, Redshift","title":"ETL / ELT / Batch Processing"},{"location":"Cloud/AWS/#application-services","text":"Notifications: SNS (alerts by email, SMS...), SES (bulk email) Queue: SQS (async message queues for component decoupling) Workflows, State Machine as a Service: AWS Step Functions, SWF (task-oriented workflows - complicated) Document Search: ElasticSearch, CloudSearch","title":"Application Services"},{"location":"Cloud/AWS/#monitoring","text":"Cloudwatch (monitor services and instances e.g. CPU utilization, etc...) CloudTrail (monitor API calls)","title":"Monitoring"},{"location":"Cloud/AWS/#infrastructure-deployment--automation","text":"Elastic Beanstalk (simple, mostly web or Linux worker) CloudFormation (JSON / YAML templates - more difficult, but many existing templates) OpsWork (higher level than CloudFormation, uses non-native components - Chef-based)","title":"Infrastructure Deployment / Automation"},{"location":"Cloud/AWS/#desktop-in-the-cloud","text":"WorkSpaces","title":"Desktop in the Cloud"},{"location":"Cloud/AWS/#details","text":"","title":"Details"},{"location":"Cloud/AWS/#tools","text":"Unix tools on Windows: Cygwin Putty SSH client for Windows doc Download and install PuTTY link . Be sure to install the entire suite. Start PuTTYgen (for example, from the Start menu, click All Programs > PuTTY > PuTTYgen). Under Type of key to generate, select SSH-2 RSA. Load the .pem file (private key) downloaded from the console (in \"credentials\" folder) Save private key AWS command line interface AWS toolkit for Visual Studio AWS tools for PowerShell","title":"Tools"},{"location":"Cloud/AWS/#aws-ec2","text":"Log onto instance with Putty SSH login as: ec2-user (Amazon Linux) or: ubuntu Bash shell documentation Use a shell script to configure the instance link User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the \"As file\" option and browse for the file to attach.","title":"AWS EC2"},{"location":"Cloud/AWS/#aws-s3","text":"GUI tools to upload / manage files: AWS Console S3 Browser CloudBerry Command-line s3 clients: AWS command line (see above) S3 command line tools","title":"AWS S3"},{"location":"Cloud/AWS/#redshift","text":"1) Use Case Large-scale SQL analytical database Querying in Redshift is FAST Full SQL compared to HiveQL Redshift isn\u2019t a complete replacement for a Hadoop system (no streaming, no text processing) 2) Tools install SQL tool or Aginity Microsoft SSDT 3) Get data into Redshift: COPY from S3 (delimited text files) COPY from DynamoDB (NoSQL datastore) JDBC/ODBC transactions (not efficient for bulk loading) Tables have \u2018keys\u2019 that define how the data is split across slices. The recommended practice is to split based upon commonly-joined columns, so that joined data resides on the same slice, thus avoiding the need to move data between systems. 4) Examples: COPY table1 FROM 's3://bucket1/' credentials 'aws_access_key_id=abc;aws_secret_access_key=xyz' delimiter '|' gzip removequotes truncatecolumns maxerror 1000 SELECT DISTINCT field1 FROM table1 SELECT COUNT ( DISTINCT field2 ) FROM table1","title":"Redshift"},{"location":"Cloud/AWS/#emr","text":"EMR FAQs Extract, Transform, and Load (ETL) Data with Amazon EMR EMR article","title":"EMR"},{"location":"Cloud/AWS/#swf","text":"The Amazon Simple Workflow Service (Amazon SWF) makes it easy to build applications that coordinate work across distributed components. In Amazon SWF, a task represents a logical unit of work that is performed by a component of your application. Coordinating tasks across the application involves managing intertask dependencies, scheduling, and concurrency in accordance with the logical flow of the application. Amazon SWF gives you full control over implementing tasks and coordinating them without worrying about underlying complexities such as tracking their progress and maintaining their state. When using Amazon SWF, you implement workers to perform tasks. These workers can run either on cloud infrastructure, such as Amazon Elastic Compute Cloud (Amazon EC2), or on your own premises. You can create tasks that are long-running, or that may fail, time out, or require restarts\u2014or that may complete with varying throughput and latency. Amazon SWF stores tasks and assigns them to workers when they are ready, tracks their progress, and maintains their state, including details on their completion. To coordinate tasks, you write a program that gets the latest state of each task from Amazon SWF and uses it to initiate subsequent tasks. Amazon SWF maintains an application's execution state durably so that the application is resilient to failures in individual components. With Amazon SWF, you can implement, deploy, scale, and modify these application components independently. Amazon SWF offers capabilities to support a variety of application requirements. It is suitable for a range of use cases that require coordination of tasks, including media processing, web application back-ends, business process workflows, and analytics pipelines.","title":"SWF"},{"location":"Cloud/AWS_Lambda/","text":"Useful Links \u00b6 Building a Dynamic DNS for Route 53 using CloudWatch Events and Lambda Lambkin - CLI tool for generating and managing simple functions in AWS Lambda","title":"AWS Lambda"},{"location":"Cloud/AWS_Lambda/#useful-links","text":"Building a Dynamic DNS for Route 53 using CloudWatch Events and Lambda Lambkin - CLI tool for generating and managing simple functions in AWS Lambda","title":"Useful Links"},{"location":"Cloud/Serverless/","text":"Serverless Cheatsheet \u00b6 Serverless home page Install \u00b6 npm install -g serverless Examples \u00b6 Serverless Examples Serverless Starter Python example C# example Cheatsheet \u00b6 Create a Service: # NodeJS serverless create -p [ SERVICE NAME ] -t aws-nodejs # C# serverless create --path serverlessCSharp --template aws-csharp Install a Service This is a convenience method to install a pre-made Serverless Service locally by downloading the Github repo and unzipping it. serverless install -u [ GITHUB URL OF SERVICE ] Deploy All Use this when you have made changes to your Functions, Events or Resources in serverless.yml or you simply want to deploy all changes within your Service at the same time. serverless deploy -s [ STAGE NAME ] -r [ REGION NAME ] -v Deploy Function Use this to quickly overwrite your AWS Lambda code on AWS, allowing you to develop faster. serverless deploy function -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ] Invoke Function Invokes an AWS Lambda Function on AWS and returns logs. serverless invoke -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ] -l Streaming Logs Open up a separate tab in your console and stream all logs for a specific Function using this command. serverless logs -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ]","title":"Serverless Cheatsheet"},{"location":"Cloud/Serverless/#serverless-cheatsheet","text":"Serverless home page","title":"Serverless Cheatsheet"},{"location":"Cloud/Serverless/#install","text":"npm install -g serverless","title":"Install"},{"location":"Cloud/Serverless/#examples","text":"Serverless Examples Serverless Starter Python example C# example","title":"Examples"},{"location":"Cloud/Serverless/#cheatsheet","text":"Create a Service: # NodeJS serverless create -p [ SERVICE NAME ] -t aws-nodejs # C# serverless create --path serverlessCSharp --template aws-csharp Install a Service This is a convenience method to install a pre-made Serverless Service locally by downloading the Github repo and unzipping it. serverless install -u [ GITHUB URL OF SERVICE ] Deploy All Use this when you have made changes to your Functions, Events or Resources in serverless.yml or you simply want to deploy all changes within your Service at the same time. serverless deploy -s [ STAGE NAME ] -r [ REGION NAME ] -v Deploy Function Use this to quickly overwrite your AWS Lambda code on AWS, allowing you to develop faster. serverless deploy function -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ] Invoke Function Invokes an AWS Lambda Function on AWS and returns logs. serverless invoke -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ] -l Streaming Logs Open up a separate tab in your console and stream all logs for a specific Function using this command. serverless logs -f [ FUNCTION NAME ] -s [ STAGE NAME ] -r [ REGION NAME ]","title":"Cheatsheet"},{"location":"Containers/Debug_Kubernetes/","text":"Run a test Docker container \u00b6 docker run --rm -p : : docker ps # cleanup docker kill To override the entrypoint, use: winpty docker run --rm -p : -it --entrypoint bash : The above assumes you are using cygwin / git bash on Windows. Run a test K8s pod \u00b6 kubectl run --image = : Useful options: - --restart=Never - if the pod has a console: -i --tty --command -- bash Attach to the (first) container in the Pod: kubectl attach -i -t If there are multiple containers in the pod, use: -c Get a shell to a running Container: kubectl exec -it -- bash Delete test pod: kubectl delete pod ","title":"Debug Kubernetes"},{"location":"Containers/Debug_Kubernetes/#run-a-test-docker-container","text":"docker run --rm -p : : docker ps # cleanup docker kill To override the entrypoint, use: winpty docker run --rm -p : -it --entrypoint bash : The above assumes you are using cygwin / git bash on Windows.","title":"Run a test Docker container"},{"location":"Containers/Debug_Kubernetes/#run-a-test-k8s-pod","text":"kubectl run --image = : Useful options: - --restart=Never - if the pod has a console: -i --tty --command -- bash Attach to the (first) container in the Pod: kubectl attach -i -t If there are multiple containers in the pod, use: -c Get a shell to a running Container: kubectl exec -it -- bash Delete test pod: kubectl delete pod ","title":"Run a test K8s pod"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/","text":"Useful Links \u00b6 Deploying scala sbt microservice to Kubernetes SBT Native Packager - Docker OpenSSL Helm Deployment of a sbt -built app on Kubernetes (MiniKube) \u00b6 Test packaging without Kubernetes first \u00b6 Stage all Play files in a local directory and verify sbt stage For direct deployment, create a distribution in target/universal sbt dist The dist task builds a binary version of your application that you can deploy to a server without any dependency on SBT, the only thing the server needs is a Java installation. Deploy a Helm chart to Kubernetes \u00b6 Prerequisites: minikube , kubectl , docker client and helm should be installed Generate the Dockerfile and environment prepared for creating a Docker image sbt docker:stage Verify the output under target/docker Start minikube minikube start Enable Ingress minikube addons list minikube addons enable ingress Also consider enabling heapster List available nodes to verify that kubectl is properly configured kubectl get nodes It should return one node. Connect the Docker client to the Docker daemon in the K8s VM eval $( minikube docker-env ) Just make sure you tag your Docker image with something other than \u2018latest\u2019 and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as :latest , with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. If needed, remove previously built images from the local Docker server with sbt docker:clean or docker rmi . To view the list of Docker images, run docker images Build the Docker image and publish it to Kubernetes' Docker server. sbt docker:publishLocal Deploy the Helm chart ./helm install --dry-run --debug & > output.txt and if that looks OK ./helm install or specify a release name: ./helm install --name Verify the Helm deployment to minikube ./helm list ./helm status More details via: kubectl get ing kubectl get service kubectl get deployment kubectl get pods Test the deployment by forwarding a local port to a port on the pod kubectl get pods kubectl port-forward 8080 : curl -v http://localhost:8080/api kubectl port-forward also allows using resource name, such as a service name, to select a matching pod to port forward to kubectl port-forward svc/ 8080 : curl -v http://localhost:8080/ When needed, delete the release with helm ls helm delete If you want to deploy / not deploy an Ingress \u00b6 Update values.yaml in the Helm chart root folder ingress : enabled : true # or: false; true by default If true, make sure the minikube Ingress add-on is enabled minikube addons enable ingress Deploy on Kubernetes as above See Blog SSL Termination (TO DO) \u00b6 IBM Ingress TLS tutorial Generate a x509, pem encoded, RSA 2048 certificate with OpenSSL openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${ KEY_FILE } -out ${ CERT_FILE } -subj \"/CN= ${ HOST } /O= ${ HOST } \" openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj \"/CN=john-cd.com\" Note: To find myhost.com for minikube, run the following commands: $ minikube ssh $ echo $HOSTNAME minikube Create a Kubernetes secret kubectl create secret tls ${ CERT_NAME } --key ${ KEY_FILE } --cert ${ CERT_FILE } kubectl create secret tls my-secret --key tls.key --cert tls.crt Add under spec: in tls : - hosts : - myhost.com secretName : my-secret Find and delete all nginx pods to force the nginx.conf to update and reflect the ingress changes. Find the ingress pods with the following: kubectl get pods --all-namespaces kubectl delete pods --namespace = kube-system [ ingress pod ]","title":"Deploy to Kubernetes (Helm)"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#useful-links","text":"Deploying scala sbt microservice to Kubernetes SBT Native Packager - Docker OpenSSL Helm","title":"Useful Links"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#deployment-of-a-sbt-built-app-on-kubernetes-minikube","text":"","title":"Deployment of a sbt-built app on Kubernetes (MiniKube)"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#test-packaging-without-kubernetes-first","text":"Stage all Play files in a local directory and verify sbt stage For direct deployment, create a distribution in target/universal sbt dist The dist task builds a binary version of your application that you can deploy to a server without any dependency on SBT, the only thing the server needs is a Java installation.","title":"Test packaging without Kubernetes first"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#deploy-a-helm-chart-to-kubernetes","text":"Prerequisites: minikube , kubectl , docker client and helm should be installed Generate the Dockerfile and environment prepared for creating a Docker image sbt docker:stage Verify the output under target/docker Start minikube minikube start Enable Ingress minikube addons list minikube addons enable ingress Also consider enabling heapster List available nodes to verify that kubectl is properly configured kubectl get nodes It should return one node. Connect the Docker client to the Docker daemon in the K8s VM eval $( minikube docker-env ) Just make sure you tag your Docker image with something other than \u2018latest\u2019 and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as :latest , with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. If needed, remove previously built images from the local Docker server with sbt docker:clean or docker rmi . To view the list of Docker images, run docker images Build the Docker image and publish it to Kubernetes' Docker server. sbt docker:publishLocal Deploy the Helm chart ./helm install --dry-run --debug & > output.txt and if that looks OK ./helm install or specify a release name: ./helm install --name Verify the Helm deployment to minikube ./helm list ./helm status More details via: kubectl get ing kubectl get service kubectl get deployment kubectl get pods Test the deployment by forwarding a local port to a port on the pod kubectl get pods kubectl port-forward 8080 : curl -v http://localhost:8080/api kubectl port-forward also allows using resource name, such as a service name, to select a matching pod to port forward to kubectl port-forward svc/ 8080 : curl -v http://localhost:8080/ When needed, delete the release with helm ls helm delete ","title":"Deploy a Helm chart to Kubernetes"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#if-you-want-to-deploy--not-deploy-an-ingress","text":"Update values.yaml in the Helm chart root folder ingress : enabled : true # or: false; true by default If true, make sure the minikube Ingress add-on is enabled minikube addons enable ingress Deploy on Kubernetes as above See Blog","title":"If you want to deploy / not deploy an Ingress"},{"location":"Containers/Deploy_to_Kubernetes%20%20%28Helm%29/#ssl-termination-to-do","text":"IBM Ingress TLS tutorial Generate a x509, pem encoded, RSA 2048 certificate with OpenSSL openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${ KEY_FILE } -out ${ CERT_FILE } -subj \"/CN= ${ HOST } /O= ${ HOST } \" openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj \"/CN=john-cd.com\" Note: To find myhost.com for minikube, run the following commands: $ minikube ssh $ echo $HOSTNAME minikube Create a Kubernetes secret kubectl create secret tls ${ CERT_NAME } --key ${ KEY_FILE } --cert ${ CERT_FILE } kubectl create secret tls my-secret --key tls.key --cert tls.crt Add under spec: in tls : - hosts : - myhost.com secretName : my-secret Find and delete all nginx pods to force the nginx.conf to update and reflect the ingress changes. Find the ingress pods with the following: kubectl get pods --all-namespaces kubectl delete pods --namespace = kube-system [ ingress pod ]","title":"SSL Termination (TO DO)"},{"location":"Containers/Deploy_to_Kubernetes/","text":"using kubectl Create ConfigMap from config files \u00b6 A ConfigMap stores K8s-specific configuration that can be mounted as volume or used in env variables. It is often used to provide production configuration: application configuration, log settings, etc... kubectl create configmap app-conf --from-file = # create a ConfigMap from multiple files in the same directory. Check the ConfigMap kubectl get configmap app-conf -o yaml # or kubectl describe configmaps app-conf Create a Kubernetes secret \u00b6 You may need a Secret to store database passwords and secret keys. For applications using the Play Framework , generate a secret using: secretText = $( sbt playGenerateSecret ) regex = \"Generated new secret: (.+) $ \" f [[ $secretText = ~ $regex ]] then secret = \" ${ BASH_REMATCH [1] } \" echo $secret kubectl create secret generic application-secret --from-literal = application_secret = $secret kubectl get secrets else echo \" $secretText doesn't match\" > & 2 fi done Create Resources (Deployment, Service, Ingress, etc...) \u00b6 kubectl create -f Verify proper resource creation kubectl get ing kubectl get service kubectl get deployment kubectl get pods To delete a resource later, in this case a Deployment: kubectl delete deployment Install an Ingress Controller \u00b6 An ingress controller is necessary to make Ingresses work. See the Ingress doc Minikube \u00b6 minikube provides its own ingress controller via the Ingress add-on: minikube addons enable ingress Enabling the add-on provisions the following: a configMap for the Nginx loadbalancer the Nginx ingress controller a service that exposes a default Nginx backend pod for handling unmapped requests. Install the nginx ingress controller (non-minikube Kubernetes) \u00b6 Install via this helm chart #./helm install stable/nginx-ingress or with stat collection enabled for Prometheus helm install --name nginx-ingress-release stable/nginx-ingress \\ --set controller.stats.enabled = true \\ --set controller.metrics.enabled = true Verify that the Ingress exists kubectl get ing See explanations and documentation The nginx ingress controller requires a 404-server like this Alternative ingress controllers \u00b6 Install https://traefik.io/","title":"Deploy to Kubernetes"},{"location":"Containers/Deploy_to_Kubernetes/#create-configmap-from-config-files","text":"A ConfigMap stores K8s-specific configuration that can be mounted as volume or used in env variables. It is often used to provide production configuration: application configuration, log settings, etc... kubectl create configmap app-conf --from-file = # create a ConfigMap from multiple files in the same directory. Check the ConfigMap kubectl get configmap app-conf -o yaml # or kubectl describe configmaps app-conf","title":"Create ConfigMap from config files"},{"location":"Containers/Deploy_to_Kubernetes/#create-a-kubernetes-secret","text":"You may need a Secret to store database passwords and secret keys. For applications using the Play Framework , generate a secret using: secretText = $( sbt playGenerateSecret ) regex = \"Generated new secret: (.+) $ \" f [[ $secretText = ~ $regex ]] then secret = \" ${ BASH_REMATCH [1] } \" echo $secret kubectl create secret generic application-secret --from-literal = application_secret = $secret kubectl get secrets else echo \" $secretText doesn't match\" > & 2 fi done","title":"Create a Kubernetes secret"},{"location":"Containers/Deploy_to_Kubernetes/#create-resources-deployment-service-ingress-etc","text":"kubectl create -f Verify proper resource creation kubectl get ing kubectl get service kubectl get deployment kubectl get pods To delete a resource later, in this case a Deployment: kubectl delete deployment ","title":"Create Resources (Deployment, Service, Ingress, etc...)"},{"location":"Containers/Deploy_to_Kubernetes/#install-an-ingress-controller","text":"An ingress controller is necessary to make Ingresses work. See the Ingress doc","title":"Install an Ingress Controller"},{"location":"Containers/Deploy_to_Kubernetes/#minikube","text":"minikube provides its own ingress controller via the Ingress add-on: minikube addons enable ingress Enabling the add-on provisions the following: a configMap for the Nginx loadbalancer the Nginx ingress controller a service that exposes a default Nginx backend pod for handling unmapped requests.","title":"Minikube"},{"location":"Containers/Deploy_to_Kubernetes/#install-the-nginx-ingress-controller-non-minikube-kubernetes","text":"Install via this helm chart #./helm install stable/nginx-ingress or with stat collection enabled for Prometheus helm install --name nginx-ingress-release stable/nginx-ingress \\ --set controller.stats.enabled = true \\ --set controller.metrics.enabled = true Verify that the Ingress exists kubectl get ing See explanations and documentation The nginx ingress controller requires a 404-server like this","title":"Install the nginx ingress controller (non-minikube Kubernetes)"},{"location":"Containers/Deploy_to_Kubernetes/#alternative-ingress-controllers","text":"Install https://traefik.io/","title":"Alternative ingress controllers"},{"location":"Containers/Docker/","text":"Docker Cheatsheet \u00b6 Useful Links \u00b6 Docker Cheat Sheet Docker Documentation Docker Tutorials and Labs Docker + Jenkins Docker Hub Concepts \u00b6 A Docker image is a read-only template. For example, an image could contain an Ubuntu operating system with Apache and your web application installed. Images are used to create Docker containers. Docker provides a simple way to build new images or update existing images, or you can download Docker images that other people have already created. Docker images are the buildcomponent of Docker. Docker registries hold images. Cheatsheet \u00b6 To show only running containers use: $ docker ps To show all containers use: $ docker ps -a Show last started container: $ docker ps -l Download an image: $ docker pull centos Create then start a container: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] * Docker run reference $ docker run hello-world Run with interactive terminal (i = interactive t = terminal): $ docker run -it ubuntu bash Start then detach the container (daemonize): $ docker run -d -p8088:80 --name webserver nginx If you want a transient container, docker run --rm will remove the container after it stops. Looks inside the container (use -f to act like tail -f ): $ docker logs Stop container: $ docker stop # container ID or name Delete container: $ docker rm To check the environment: $ docker run -it alpine env Docker version / info: $ docker version $ docker info Port Mapping \u00b6 -p 80:5000 would map port 80 on our local host to port 5000 inside our container. $ docker run -d -p 80 :5000 training/webapp python app.py Full format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort $ docker run -d -p 127 .0.0.1:80:5000 training/webapp python app.py Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: -p1234-1236:1234-1236/tcp The -P flag tells Docker to map any required network ports inside our container to our host (using random ports). $ docker run -d -P training/webapp python app.py Linking \u00b6 --link :alias where name is the name of the container we\u2019re linking to and alias is an alias for the link name. The --link flag also takes the form: --link $ docker run -d --name myES -p 9200 :9200 -p 9300 :9300 elasticsearch $ docker run --name myK --link myES:elasticsearch -p 5601 :5601 -d docker-kibana-sense Networks \u00b6 $ docker network ls Find out the container\u2019s IP address: $ docker network inspect bridge Data Volumes \u00b6 Create a new volume inside a container at /webapp: $ docker run -d -P --name web -v /webapp training/webapp python app.py $ docker inspect web You can also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image. Mount the host directory, /src/webapp , into the container at /opt/webapp . $ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py On Windows, use: docker run -v /c/Users/:/ ... Example Dockerfile \u00b6 $ vim Dockerfile FROM docker/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes CMD /usr/games/fortune -a | cowsay $ docker build -t docker-whale .","title":"Docker Cheatsheet"},{"location":"Containers/Docker/#docker-cheatsheet","text":"","title":"Docker Cheatsheet"},{"location":"Containers/Docker/#useful-links","text":"Docker Cheat Sheet Docker Documentation Docker Tutorials and Labs Docker + Jenkins Docker Hub","title":"Useful Links"},{"location":"Containers/Docker/#concepts","text":"A Docker image is a read-only template. For example, an image could contain an Ubuntu operating system with Apache and your web application installed. Images are used to create Docker containers. Docker provides a simple way to build new images or update existing images, or you can download Docker images that other people have already created. Docker images are the buildcomponent of Docker. Docker registries hold images.","title":"Concepts"},{"location":"Containers/Docker/#cheatsheet","text":"To show only running containers use: $ docker ps To show all containers use: $ docker ps -a Show last started container: $ docker ps -l Download an image: $ docker pull centos Create then start a container: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] * Docker run reference $ docker run hello-world Run with interactive terminal (i = interactive t = terminal): $ docker run -it ubuntu bash Start then detach the container (daemonize): $ docker run -d -p8088:80 --name webserver nginx If you want a transient container, docker run --rm will remove the container after it stops. Looks inside the container (use -f to act like tail -f ): $ docker logs Stop container: $ docker stop # container ID or name Delete container: $ docker rm To check the environment: $ docker run -it alpine env Docker version / info: $ docker version $ docker info","title":"Cheatsheet"},{"location":"Containers/Docker/#port-mapping","text":"-p 80:5000 would map port 80 on our local host to port 5000 inside our container. $ docker run -d -p 80 :5000 training/webapp python app.py Full format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort $ docker run -d -p 127 .0.0.1:80:5000 training/webapp python app.py Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: -p1234-1236:1234-1236/tcp The -P flag tells Docker to map any required network ports inside our container to our host (using random ports). $ docker run -d -P training/webapp python app.py","title":"Port Mapping"},{"location":"Containers/Docker/#linking","text":"--link :alias where name is the name of the container we\u2019re linking to and alias is an alias for the link name. The --link flag also takes the form: --link $ docker run -d --name myES -p 9200 :9200 -p 9300 :9300 elasticsearch $ docker run --name myK --link myES:elasticsearch -p 5601 :5601 -d docker-kibana-sense","title":"Linking"},{"location":"Containers/Docker/#networks","text":"$ docker network ls Find out the container\u2019s IP address: $ docker network inspect bridge","title":"Networks"},{"location":"Containers/Docker/#data-volumes","text":"Create a new volume inside a container at /webapp: $ docker run -d -P --name web -v /webapp training/webapp python app.py $ docker inspect web You can also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image. Mount the host directory, /src/webapp , into the container at /opt/webapp . $ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py On Windows, use: docker run -v /c/Users/:/ ...","title":"Data Volumes"},{"location":"Containers/Docker/#example-dockerfile","text":"$ vim Dockerfile FROM docker/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes CMD /usr/games/fortune -a | cowsay $ docker build -t docker-whale .","title":"Example Dockerfile"},{"location":"Containers/Helm_Chart_Creation/","text":"Links \u00b6 How to create your first Helm chart Steps \u00b6 ./helm create ./helm lint ./helm install --dry-run --debug To create dependencies between charts \u00b6 Create requirements.yaml Add a remote repo ./helm repo add stable https://kubernetes-charts.storage.googleapis.com and, from the chart directory, run: ../helm dependency update","title":"Helm Chart Creation"},{"location":"Containers/Helm_Chart_Creation/#links","text":"How to create your first Helm chart","title":"Links"},{"location":"Containers/Helm_Chart_Creation/#steps","text":"./helm create ./helm lint ./helm install --dry-run --debug ","title":"Steps"},{"location":"Containers/Helm_Chart_Creation/#to-create-dependencies-between-charts","text":"Create requirements.yaml Add a remote repo ./helm repo add stable https://kubernetes-charts.storage.googleapis.com and, from the chart directory, run: ../helm dependency update","title":"To create dependencies between charts"},{"location":"Containers/Kubernetes_Cheatsheet/","text":"minikube \u00b6 To access the Kubernetes Dashboard, run this command in a shell after starting Minikube to get the address: minikube dashboard The minikube VM is exposed to the host system via a host-only IP address, that can be obtained with the minikube ip command kubectl \u00b6 kubectl Cheat Sheet Run a particular image on the cluster (creates a deployment automatically) kubectl run hello-world --replicas = 2 --labels = \"run=load-balancer-example\" --image = gcr.io/google-samples/node-hello:1.0 --port = 8080 kubectl get - list resources. kubectl get deployment to get all deployments kubectl get pods -l app=nginx to get pods with label \"app: nginx\" kubectl describe - show detailed information about a resource kubectl logs - print the logs from a container in a pod kubectl exec - execute a command on a container in a pod Using the Docker daemon in the Minikube VM \u00b6 When using a single VM of Kubernetes, it\u2019s really handy to reuse the minikube\u2019s built-in Docker daemon eval $( minikube docker-env ) # test with docker ps Just make sure you tag your Docker image with something other than \u2018latest\u2019 and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as :latest , with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. See installing Docker for instructions for your platform.","title":"Kubernetes Cheatsheet"},{"location":"Containers/Kubernetes_Cheatsheet/#minikube","text":"To access the Kubernetes Dashboard, run this command in a shell after starting Minikube to get the address: minikube dashboard The minikube VM is exposed to the host system via a host-only IP address, that can be obtained with the minikube ip command","title":"minikube"},{"location":"Containers/Kubernetes_Cheatsheet/#kubectl","text":"kubectl Cheat Sheet Run a particular image on the cluster (creates a deployment automatically) kubectl run hello-world --replicas = 2 --labels = \"run=load-balancer-example\" --image = gcr.io/google-samples/node-hello:1.0 --port = 8080 kubectl get - list resources. kubectl get deployment to get all deployments kubectl get pods -l app=nginx to get pods with label \"app: nginx\" kubectl describe - show detailed information about a resource kubectl logs - print the logs from a container in a pod kubectl exec - execute a command on a container in a pod","title":"kubectl"},{"location":"Containers/Kubernetes_Cheatsheet/#using-the-docker-daemon-in-the-minikube-vm","text":"When using a single VM of Kubernetes, it\u2019s really handy to reuse the minikube\u2019s built-in Docker daemon eval $( minikube docker-env ) # test with docker ps Just make sure you tag your Docker image with something other than \u2018latest\u2019 and use that tag while you pull the image. Otherwise, if you do not specify version of your image, it will be assumed as :latest , with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet. A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. See installing Docker for instructions for your platform.","title":"Using the Docker daemon in the Minikube VM"},{"location":"Containers/Kubernetes_Concepts/","text":"Pods - A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. Kubernetes workloads, such as Deployments and Jobs, are composed of one or more Pods. Shared pod resources include: Shared storage, as Volumes Networking, as a unique cluster IP address Information about how to run each container, such as the container image version or specific ports to use Nodes: A Pod always runs on a Node. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster. Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster. Deployment - The most common way of running X copies (Pods) of your application. Supports rolling updates to your container images. Service - By itself, a Deployment can\u2019t receive traffic. Setting up a Service is one of the simplest ways to configure a Deployment to receive and loadbalance requests. Depending on the type of Service used, these requests can come from external client apps or be limited to apps within the same cluster. A Service is tied to a specific Deployment using label selection. Labels - Identifying metadata that you can use to sort and select sets of API objects. Labels have many applications, including the following: To keep the right number of replicas (Pods) running in a Deployment. The specified label is used to stamp the Deployment\u2019s newly created Pods (as the value of the spec.template.labels configuration field), and to query which Pods it already manages (as the value of spec.selector.matchLabels ). To tie a Service to a Deployment using the selector field. To look for specific subset of Kubernetes objects, when you are using kubectl. For instance, the command kubectl get deployments --selector=app=nginx only displays Deployments from the nginx app.","title":"Kubernetes Concepts"},{"location":"Containers/Kubernetes_Examples/","text":"Service + Deployment example \u00b6 apiVersion : v1 kind : Service metadata : name : p2p-robot-service spec : selector : app : p2p-robot ports : - name : http protocol : TCP port : 80 targetPort : http # can a text label (port name) or port number --- apiVersion : apps/v1 kind : Deployment metadata : name : p2p-robot-deployment spec : selector : matchLabels : app : p2p-robot replicas : 2 # tells deployment to run 2 pods matching the template template : # create pods using pod definition in this template metadata : # the name is not included in the meta data as a unique name is # generated from the deployment name labels : app : p2p-robot # label used above in matchLabels spec : containers : - name : p2p-robot image : \"johncd/p2p-robot:1.0.0\" imagePullPolicy : IfNotPresent ports : - containerPort : 9000 name : http env : - name : APPLICATION_SECRET # Place the application secret in an environment variable, which is read in application.conf valueFrom : secretKeyRef : name : application-secret key : application_secret volumeMounts : - name : conf-volume mountPath : /usr/local/etc volumes : - name : conf-volume configMap : # The configMap resource provides a way to inject configuration data into Pods. name : app-conf Ingress example \u00b6 # Ingress # https://kubernetes.io/docs/concepts/services-networking/ingress/ apiVersion : extensions/v1beta1 kind : Ingress metadata : name : test annotations : ingress.kubernetes.io/rewrite-target : / kubernetes.io/ingress.class : nginx # Use the nginx-ingress Ingress controller spec : tls : - secretName : ingresssecret # Referencing this secret in an Ingress will tell the Ingress controller to secure the channel from the client to the loadbalancer using TLS rules : - http : paths : - path : /api backend : serviceName : s1 servicePort : 80 --- # Secure the Ingress by specifying a secret that contains a TLS private key and certificate. apiVersion : v1 data : tls.crt : base64 encoded cert tls.key : base64 encoded key kind : Secret metadata : name : ingresssecret namespace : default type : Opaque","title":"Kubernetes Examples"},{"location":"Containers/Kubernetes_Examples/#service--deployment-example","text":"apiVersion : v1 kind : Service metadata : name : p2p-robot-service spec : selector : app : p2p-robot ports : - name : http protocol : TCP port : 80 targetPort : http # can a text label (port name) or port number --- apiVersion : apps/v1 kind : Deployment metadata : name : p2p-robot-deployment spec : selector : matchLabels : app : p2p-robot replicas : 2 # tells deployment to run 2 pods matching the template template : # create pods using pod definition in this template metadata : # the name is not included in the meta data as a unique name is # generated from the deployment name labels : app : p2p-robot # label used above in matchLabels spec : containers : - name : p2p-robot image : \"johncd/p2p-robot:1.0.0\" imagePullPolicy : IfNotPresent ports : - containerPort : 9000 name : http env : - name : APPLICATION_SECRET # Place the application secret in an environment variable, which is read in application.conf valueFrom : secretKeyRef : name : application-secret key : application_secret volumeMounts : - name : conf-volume mountPath : /usr/local/etc volumes : - name : conf-volume configMap : # The configMap resource provides a way to inject configuration data into Pods. name : app-conf","title":"Service + Deployment example"},{"location":"Containers/Kubernetes_Examples/#ingress-example","text":"# Ingress # https://kubernetes.io/docs/concepts/services-networking/ingress/ apiVersion : extensions/v1beta1 kind : Ingress metadata : name : test annotations : ingress.kubernetes.io/rewrite-target : / kubernetes.io/ingress.class : nginx # Use the nginx-ingress Ingress controller spec : tls : - secretName : ingresssecret # Referencing this secret in an Ingress will tell the Ingress controller to secure the channel from the client to the loadbalancer using TLS rules : - http : paths : - path : /api backend : serviceName : s1 servicePort : 80 --- # Secure the Ingress by specifying a secret that contains a TLS private key and certificate. apiVersion : v1 data : tls.crt : base64 encoded cert tls.key : base64 encoded key kind : Secret metadata : name : ingresssecret namespace : default type : Opaque","title":"Ingress example"},{"location":"Containers/Minikube_Install_in_Ubuntu_on_Windows/","text":"Install kubectl in Ubuntu on Windows \u00b6 cd ~ mkdir bin curl -LO https://storage.googleapis.com/kubernetes-release/release/ $( curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt ) /bin/linux/amd64/kubectl chmod +x ./kubectl # optionally sudo mv ./kubectl /usr/local/bin/kubectl # then test kubectl get all # enable autocompletion source < ( kubectl completion bash ) echo \"source <(kubectl completion bash)\" >> ~/.bashrc If necessary, install socat sudo apt-get update && sudo apt-get install socat In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using kube-up.sh or successfully deploy a Minikube cluster. Check that kubectl is properly configured by getting the cluster state: kubectl cluster-info Beware that you may have two different config files in ~/.kube/ and /mnt/c/Users//.kube if you installed minikube in Windows.","title":"Minikube Install in Ubuntu on Windows"},{"location":"Containers/Minikube_Install_in_Ubuntu_on_Windows/#install-kubectl-in-ubuntu-on-windows","text":"cd ~ mkdir bin curl -LO https://storage.googleapis.com/kubernetes-release/release/ $( curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt ) /bin/linux/amd64/kubectl chmod +x ./kubectl # optionally sudo mv ./kubectl /usr/local/bin/kubectl # then test kubectl get all # enable autocompletion source < ( kubectl completion bash ) echo \"source <(kubectl completion bash)\" >> ~/.bashrc If necessary, install socat sudo apt-get update && sudo apt-get install socat In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using kube-up.sh or successfully deploy a Minikube cluster. Check that kubectl is properly configured by getting the cluster state: kubectl cluster-info Beware that you may have two different config files in ~/.kube/ and /mnt/c/Users//.kube if you installed minikube in Windows.","title":"Install kubectl in Ubuntu on Windows"},{"location":"Containers/Minikube_Install_on_Windows/","text":"Install minikube on Windows \u00b6 Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day. For Windows, install VirtualBox or Hyper-V first. Minikube is distributed in binary form: GitHub Repo . Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well. If needed, add C:\\Program Files (x86)\\Kubernetes\\minikube or similar to the PATH (in System Settings > Environment Variables ) Test that minikube works: $ minikube More info at Getting Started Install kubectl \u00b6 Use a version of kubectl that is the same version as your server or later. Using an older kubectl with a newer server might produce validation errors. On Windows 10 (using Git Bash): curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/windows/amd64/kubectl.exe OR Install Choco Then choco install kubernetes-cli Run kubectl version to verify that the version you\u2019ve installed is sufficiently up-to-date. kubectl version Configure kubectl \u00b6 Configure kubectl to use a remote Kubernetes cluster If ~/.kube config does not exist (it should have been created by minikube ), enter the following in Powershell: cd C: \\u sers \\< yourusername> mkdir .kube cd .kube New-Item config -type file Edit the config file with a text editor of your choice. Check that kubectl is properly configured by getting the cluster state: kubectl cluster-info Enable auto-completion (if you use Git Bash) echo \"source <(kubectl completion bash)\" >> ~/.bashrc You must have appropriate permissions to list, create, edit and delete pods in your cluster: kubectl auth can-i list pods kubectl auth can-i create pods kubectl auth can-i edit pods kubectl auth can-i delete pods Run kubectl from the Ubuntu on Windows command line \u00b6 If installed by choco export PATH = $PATH :/mnt/c/ProgramData/chocolatey/bin/kubectl # then use: kubectl.exe Run minikube \u00b6 Running Kubernetes Locally via Minikube Install curl choco install curl Test curl curl http://google.com Start minikube minikube start List hosts kubectl get nodes Test by deploying a container (creates a deployment / pod automatically) kubectl run hello-minikube --image = k8s.gcr.io/echoserver:1.4 --port = 8080 Provide a dynamic port to the container (creates a service automatically) kubectl expose deployment hello-minikube --type = NodePort We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it via the exposed service. To check whether the pod is up and running we can use the following: kubectl get pod Once the pod is running, curl it: curl $( minikube service hello-minikube --url ) Cleanup: kubectl delete deployment hello-minikube kubectl delete service hello-minikube minikube stop Install Helm \u00b6 Helm is a package manager for Kubernetes. Download a binary release of the Helm client from here Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step: $ helm init This will install Tiller (the helm server) into the current Kubernetes cluster (as listed in kubectl config current-context ). Install a test Helm chart, then clean up helm repo update # Make sure we get the latest list of charts helm install stable/mysql helm ls helm status helm delete ","title":"Minikube Install on Windows"},{"location":"Containers/Minikube_Install_on_Windows/#install-minikube-on-windows","text":"Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day. For Windows, install VirtualBox or Hyper-V first. Minikube is distributed in binary form: GitHub Repo . Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well. If needed, add C:\\Program Files (x86)\\Kubernetes\\minikube or similar to the PATH (in System Settings > Environment Variables ) Test that minikube works: $ minikube More info at Getting Started","title":"Install minikube on Windows"},{"location":"Containers/Minikube_Install_on_Windows/#install-kubectl","text":"Use a version of kubectl that is the same version as your server or later. Using an older kubectl with a newer server might produce validation errors. On Windows 10 (using Git Bash): curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/windows/amd64/kubectl.exe OR Install Choco Then choco install kubernetes-cli Run kubectl version to verify that the version you\u2019ve installed is sufficiently up-to-date. kubectl version","title":"Install kubectl"},{"location":"Containers/Minikube_Install_on_Windows/#configure-kubectl","text":"Configure kubectl to use a remote Kubernetes cluster If ~/.kube config does not exist (it should have been created by minikube ), enter the following in Powershell: cd C: \\u sers \\< yourusername> mkdir .kube cd .kube New-Item config -type file Edit the config file with a text editor of your choice. Check that kubectl is properly configured by getting the cluster state: kubectl cluster-info Enable auto-completion (if you use Git Bash) echo \"source <(kubectl completion bash)\" >> ~/.bashrc You must have appropriate permissions to list, create, edit and delete pods in your cluster: kubectl auth can-i list pods kubectl auth can-i create pods kubectl auth can-i edit pods kubectl auth can-i delete pods","title":"Configure kubectl"},{"location":"Containers/Minikube_Install_on_Windows/#run-kubectl-from-the-ubuntu-on-windows-command-line","text":"If installed by choco export PATH = $PATH :/mnt/c/ProgramData/chocolatey/bin/kubectl # then use: kubectl.exe","title":"Run kubectl from the Ubuntu on Windows command line"},{"location":"Containers/Minikube_Install_on_Windows/#run-minikube","text":"Running Kubernetes Locally via Minikube Install curl choco install curl Test curl curl http://google.com Start minikube minikube start List hosts kubectl get nodes Test by deploying a container (creates a deployment / pod automatically) kubectl run hello-minikube --image = k8s.gcr.io/echoserver:1.4 --port = 8080 Provide a dynamic port to the container (creates a service automatically) kubectl expose deployment hello-minikube --type = NodePort We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it via the exposed service. To check whether the pod is up and running we can use the following: kubectl get pod Once the pod is running, curl it: curl $( minikube service hello-minikube --url ) Cleanup: kubectl delete deployment hello-minikube kubectl delete service hello-minikube minikube stop","title":"Run minikube"},{"location":"Containers/Minikube_Install_on_Windows/#install-helm","text":"Helm is a package manager for Kubernetes. Download a binary release of the Helm client from here Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step: $ helm init This will install Tiller (the helm server) into the current Kubernetes cluster (as listed in kubectl config current-context ). Install a test Helm chart, then clean up helm repo update # Make sure we get the latest list of charts helm install stable/mysql helm ls helm status helm delete ","title":"Install Helm"},{"location":"Data_Science/Data_Manipulation/","text":"Pandas \u00b6 Pandas cheatsheet Pandas cheatsheet 2 Data Wrangling with .NET \u00b6 Quora: Which is the best machine learning library for .NET? Deedle- Exploratory data library for .NET Deedle is an easy to use library for data and time series manipulation and for scientific programming. It supports working with structured data frames, ordered and unordered data, as well as time series. Deedle is designed to work well for exploratory programming using F# and C# interactive console, but can be also used in efficient compiled .NET code. The library implements a wide range of operations for data manipulation including advanced indexing and slicing, joining and aligning data, handling of missing values, grouping and aggregation, statistics and more. Accord.NET Framework Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET.","title":"Data Manipulation"},{"location":"Data_Science/Data_Manipulation/#pandas","text":"Pandas cheatsheet Pandas cheatsheet 2","title":"Pandas"},{"location":"Data_Science/Data_Manipulation/#data-wrangling-with-net","text":"Quora: Which is the best machine learning library for .NET? Deedle- Exploratory data library for .NET Deedle is an easy to use library for data and time series manipulation and for scientific programming. It supports working with structured data frames, ordered and unordered data, as well as time series. Deedle is designed to work well for exploratory programming using F# and C# interactive console, but can be also used in efficient compiled .NET code. The library implements a wide range of operations for data manipulation including advanced indexing and slicing, joining and aligning data, handling of missing values, grouping and aggregation, statistics and more. Accord.NET Framework Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET.","title":"Data Wrangling with .NET"},{"location":"Data_Science/Data_Visualization/","text":"Basics \u00b6 Data visualization - Wikipedia 19 Tools for Data Visualization Projects 22 free tools for data visualization and analysis - Computerworld 22 free tools for data visualization and analysis JavaScript libraries / APIs \u00b6 D3.js - Data-Driven Documents D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts. D3 building blocks C3.js Google Charts Tools \u00b6 plot.ly Tableau Qlik Quadrigram Open-source data viz \u00b6 Superset vs Metabase vs ReDash AirPal","title":"Data Visualization"},{"location":"Data_Science/Data_Visualization/#basics","text":"Data visualization - Wikipedia 19 Tools for Data Visualization Projects 22 free tools for data visualization and analysis - Computerworld 22 free tools for data visualization and analysis","title":"Basics"},{"location":"Data_Science/Data_Visualization/#javascript-libraries--apis","text":"D3.js - Data-Driven Documents D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts. D3 building blocks C3.js Google Charts","title":"JavaScript libraries / APIs"},{"location":"Data_Science/Data_Visualization/#tools","text":"plot.ly Tableau Qlik Quadrigram","title":"Tools"},{"location":"Data_Science/Data_Visualization/#open-source-data-viz","text":"Superset vs Metabase vs ReDash AirPal","title":"Open-source data viz"},{"location":"Data_Science/Deep_Learning/","text":"Libraries \u00b6 DeepLearning4j TensorFlow Caffe - Deep Learning Framework MXnet Keras Useful Links \u00b6 What is deep learning Why-is-Deep-Learning-so-popular-and-in-demand-these-days Deep Learning for beginners (deeplearning4j) The best answers to your most crucial deep learning questions Colah's blog - Neural Networks Neural Networks - Dropout Deep Learning Glossary Deep Learning for Visual Question Answering Deep Learning - RNNs \u00b6 RNNs Embed, encode, attend, predict- The new deep learning formula for state-of-the-art NLP models - Blog - Explosion AI RNN Tutorial Part 1 Part 2 Part 3 Part 4","title":"Deep Learning"},{"location":"Data_Science/Deep_Learning/#libraries","text":"DeepLearning4j TensorFlow Caffe - Deep Learning Framework MXnet Keras","title":"Libraries"},{"location":"Data_Science/Deep_Learning/#useful-links","text":"What is deep learning Why-is-Deep-Learning-so-popular-and-in-demand-these-days Deep Learning for beginners (deeplearning4j) The best answers to your most crucial deep learning questions Colah's blog - Neural Networks Neural Networks - Dropout Deep Learning Glossary Deep Learning for Visual Question Answering","title":"Useful Links"},{"location":"Data_Science/Deep_Learning/#deep-learning---rnns","text":"RNNs Embed, encode, attend, predict- The new deep learning formula for state-of-the-art NLP models - Blog - Explosion AI RNN Tutorial Part 1 Part 2 Part 3 Part 4","title":"Deep Learning - RNNs"},{"location":"Data_Science/Dimensionality_Reduction/","text":"Useful Links \u00b6 Dimensionality Reduction Visualizing MNIST- An Exploration of Dimensionality Reduction - colah's blog Seven Techniques for Dimensionality Reduction: Missing Values, Low Variance Filter, High Correlation Filter, PCA, Random Forests, Backward Feature Elimination, and Forward Feature Construction","title":"Dimensionality Reduction"},{"location":"Data_Science/Dimensionality_Reduction/#useful-links","text":"Dimensionality Reduction Visualizing MNIST- An Exploration of Dimensionality Reduction - colah's blog Seven Techniques for Dimensionality Reduction: Missing Values, Low Variance Filter, High Correlation Filter, PCA, Random Forests, Backward Feature Elimination, and Forward Feature Construction","title":"Useful Links"},{"location":"Data_Science/Keras/","text":"Useful Links \u00b6 Keras Keras Blog Building autoencoders in Keras manifold-learning-and-autoencoders Keras tutorial for Kaggle 2nd Annual Data Science Bowl Supervised Sequence Labelling with Recurrent Neural Networks Sequence Classification with LSTM Recurrent Neural Networks in Python with Keras","title":"Keras Cheatsheet"},{"location":"Data_Science/Keras/#useful-links","text":"Keras Keras Blog Building autoencoders in Keras manifold-learning-and-autoencoders Keras tutorial for Kaggle 2nd Annual Data Science Bowl Supervised Sequence Labelling with Recurrent Neural Networks Sequence Classification with LSTM Recurrent Neural Networks in Python with Keras","title":"Useful Links"},{"location":"Data_Science/Machine_Learning/","text":"Useful Links \u00b6 DataTau Datasets \u00b6 UC Irvine Machine Learning Repository Quandl Kaggle Algorithms \u00b6 Restricted Boltzmann Machines \u00b6 A Beginner's Tutorial for Restricted Boltzmann Machines - Deeplearning4j- Open-source, Distributed Deep Learning for the JVM Embedding \u00b6 t-distributed stochastic neighbor embedding - Wikipedia Reinforcement Learning \u00b6 Lecture 10 Reinforcement Learning I PyBrain PyBrain - a simple neural networks library in Python CyBrain ML Plaforms \u00b6 Palladium GUI tools \u00b6 Orange Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation together to create machine learning \u201cprograms\u201d. Provides over 100 widgets for the environment and also provides a Python API and library for integrating into your application. Weka explorer A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It also provides an experimenter where you can perform the same tasks in a controlled environment and design a batch of algorithm runs that could run for an extended period of time and then review the results. Finally, it also provides a data flow interface where you can plug algorithms together like a flow diagram. Under the covers you can use Weka as a Java library and write programs that make use of the algorithms. BigML A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for configuring algorithms (decision trees) and reviewing the results. The best feature of this service is that it is all in the cloud, meaning that all you need is a web browser to get started. It also provides an API so that if you like it you can build an application around it. Tutorials \u00b6 machinelearningmastery.com Kaggle Books \u00b6 The Elements of Statistical Learning: Data Mining, Inference, and Prediction Boosting Foundations and Algorithms","title":"Machine Learning"},{"location":"Data_Science/Machine_Learning/#useful-links","text":"DataTau","title":"Useful Links"},{"location":"Data_Science/Machine_Learning/#datasets","text":"UC Irvine Machine Learning Repository Quandl Kaggle","title":"Datasets"},{"location":"Data_Science/Machine_Learning/#algorithms","text":"","title":"Algorithms"},{"location":"Data_Science/Machine_Learning/#restricted-boltzmann-machines","text":"A Beginner's Tutorial for Restricted Boltzmann Machines - Deeplearning4j- Open-source, Distributed Deep Learning for the JVM","title":"Restricted Boltzmann Machines"},{"location":"Data_Science/Machine_Learning/#embedding","text":"t-distributed stochastic neighbor embedding - Wikipedia","title":"Embedding"},{"location":"Data_Science/Machine_Learning/#reinforcement-learning","text":"Lecture 10 Reinforcement Learning I PyBrain PyBrain - a simple neural networks library in Python CyBrain","title":"Reinforcement Learning"},{"location":"Data_Science/Machine_Learning/#ml-plaforms","text":"Palladium","title":"ML Plaforms"},{"location":"Data_Science/Machine_Learning/#gui-tools","text":"Orange Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation together to create machine learning \u201cprograms\u201d. Provides over 100 widgets for the environment and also provides a Python API and library for integrating into your application. Weka explorer A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It also provides an experimenter where you can perform the same tasks in a controlled environment and design a batch of algorithm runs that could run for an extended period of time and then review the results. Finally, it also provides a data flow interface where you can plug algorithms together like a flow diagram. Under the covers you can use Weka as a Java library and write programs that make use of the algorithms. BigML A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for configuring algorithms (decision trees) and reviewing the results. The best feature of this service is that it is all in the cloud, meaning that all you need is a web browser to get started. It also provides an API so that if you like it you can build an application around it.","title":"GUI tools"},{"location":"Data_Science/Machine_Learning/#tutorials","text":"machinelearningmastery.com Kaggle","title":"Tutorials"},{"location":"Data_Science/Machine_Learning/#books","text":"The Elements of Statistical Learning: Data Mining, Inference, and Prediction Boosting Foundations and Algorithms","title":"Books"},{"location":"Data_Science/Recommenders/","text":"Useful Links \u00b6 Recommender System Building a Recommendation Engine- An Algorithm Tutorial - Toptal Music Recognition Algorithm- How Shazam Works - Toptal","title":"Recommender Systems"},{"location":"Data_Science/Recommenders/#useful-links","text":"Recommender System Building a Recommendation Engine- An Algorithm Tutorial - Toptal Music Recognition Algorithm- How Shazam Works - Toptal","title":"Useful Links"},{"location":"Data_Science/scikit-learn/","text":"Useful Links \u00b6 Cheatsheet- Scikit-Learn & Caret Package for Python & R respectively","title":"Scikit-Learn"},{"location":"Data_Science/scikit-learn/#useful-links","text":"Cheatsheet- Scikit-Learn & Caret Package for Python & R respectively","title":"Useful Links"},{"location":"Databases/Mongodb/","text":"Import from CSV \u00b6 mongoimport --db users --collection contacts --type csv --headerline --file contacts.csv Specifying --headerline instructs mongoimport to determine the name of the fields using the first line in the CSV file. Use the --ignoreBlanks option to ignore blank fields. For CSV and TSV imports, this option provides the desired functionality in most cases, because it avoids inserting fields with null values into your collection. MongoImport documentation Print from a Cursor \u00b6 myCursor . forEach ( printjson ); // or while ( myCollection . hasNext ()) { printjson ( myCollection . next ()); } Aggregation Tips \u00b6 // lowercase a string { $project : { \"address\" : { $toLower : \"$address\" } } }, // extract field within embedded document { $project : { \"experience.location\" : 1 } }, // flatten { $unwind : \"$experience\" }, { $group : { _id : \"$_id\" , locs : { $push : { $ifNull : [ \"$experience.location\" , \"undefined\" ] } } } } // output a collection { $out : \"myCollection2\" } // get unique values { $group : { _id : \"$fulladdress\" } } Make a Copy \u00b6 Don't use copyTo - it is fully blocking... and deprecated in 3.x Use the Aggregation framework: db = db . getSiblingDB ( \"myDB\" ); // set current db for $out var myCollection = db . getCollection ( \"myCollection\" ); // project if needed, get uniques if needed, create a new collection myCollection . aggregate ([{ $project : { \"fulladdress\" : 1 } },{ $group : { _id : \"$fulladdress\" } },{ $out : \"outputCollection\" }], { allowDiskUse : true }); Or use bulk update: var outputColl = db . getCollection ( \"outputCollection\" ); var outputBulk = outputColl . initializeUnorderedBulkOp (); myCollection . find ( {}, { \"fulladdress\" : 1 } ). forEach ( function ( doc ) { outputBulk . insert ( doc ); }); outputBulk . execute (); Longer Example \u00b6 Add a count field to all records function gatherStats () { var start = Date . now (); var inputDB = db . getSiblingDB ( \"inputDB\" ); var inputColl = inputDB . getCollection ( \"inputColl\" ); // debug: inputColl.find( {} ).limit(2).forEach(printjson); outputDB = db . getSiblingDB ( \"outputDB\" ); db = outputDB ; // set current database for the next aggregate step // create temporary collection with count inputColl . aggregate ( [ { $group : { _id : { $toLower : \"$address\" }, count : { $sum : 1 } } }, { $sort : { \"count\" : - 1 } }, { $limit : 100000 }, // limit to 100k addresses with highest count { $out : \"stats\" } ], { allowDiskUse : true } ); // returns { _id, count } where _id is the address var statsColl = outputDB . getCollection ( \"stats\" ); // create output collection var outputColl = outputDB . getCollection ( \"outputColl\" ); var outputBulk = outputColl . initializeUnorderedBulkOp (); var counter = 0 ; var inputCursor = inputColl . find ( {}, {} ); inputCursor . forEach ( function ( doc ) { var statDoc = statsColl . findOne ( { _id : doc . address } ); if ( statDoc ) { doc . count = statDoc . count ; outputBulk . insert ( doc ); counter ++ ; if ( counter % 1000 == 0 ) { outputBulk . execute (); // you have to reset outputBulk = outputColl . initializeUnorderedBulkOp (); } } } ); if ( counter % 1000 > 0 ) outputBulk . execute (); // print the results outputColl . find ({}). sort ({ count : - 1 }). forEach ( printjson ); var end = Date . now (); var duration = ( end - start ) / 1000 ; printjson ( \"Duration: \" + duration + \" seconds\" ); printjson ( \" | DONE | \" ); } gatherStats (); Alternatively move data to memory: var statsDict = {}; // or better Object.create(null); statsColl . find ({}). forEach ( function ( doc ) { statsDict [ doc . _id ] = doc . count } ); // could also use: var statsArray = statsCursor.toArray(); inputCursor . forEach ( function ( doc ) { if ( doc . address in statsDict ) { doc [ \"count\" ] = statsDict [ doc . address ]; outputBulk . insert ( doc ); } }); outputBulk . execute ();","title":"MongoDB Cheatsheet"},{"location":"Databases/Mongodb/#import-from-csv","text":"mongoimport --db users --collection contacts --type csv --headerline --file contacts.csv Specifying --headerline instructs mongoimport to determine the name of the fields using the first line in the CSV file. Use the --ignoreBlanks option to ignore blank fields. For CSV and TSV imports, this option provides the desired functionality in most cases, because it avoids inserting fields with null values into your collection. MongoImport documentation","title":"Import from CSV"},{"location":"Databases/Mongodb/#print-from-a-cursor","text":"myCursor . forEach ( printjson ); // or while ( myCollection . hasNext ()) { printjson ( myCollection . next ()); }","title":"Print from a Cursor"},{"location":"Databases/Mongodb/#aggregation-tips","text":"// lowercase a string { $project : { \"address\" : { $toLower : \"$address\" } } }, // extract field within embedded document { $project : { \"experience.location\" : 1 } }, // flatten { $unwind : \"$experience\" }, { $group : { _id : \"$_id\" , locs : { $push : { $ifNull : [ \"$experience.location\" , \"undefined\" ] } } } } // output a collection { $out : \"myCollection2\" } // get unique values { $group : { _id : \"$fulladdress\" } }","title":"Aggregation Tips"},{"location":"Databases/Mongodb/#make-a-copy","text":"Don't use copyTo - it is fully blocking... and deprecated in 3.x Use the Aggregation framework: db = db . getSiblingDB ( \"myDB\" ); // set current db for $out var myCollection = db . getCollection ( \"myCollection\" ); // project if needed, get uniques if needed, create a new collection myCollection . aggregate ([{ $project : { \"fulladdress\" : 1 } },{ $group : { _id : \"$fulladdress\" } },{ $out : \"outputCollection\" }], { allowDiskUse : true }); Or use bulk update: var outputColl = db . getCollection ( \"outputCollection\" ); var outputBulk = outputColl . initializeUnorderedBulkOp (); myCollection . find ( {}, { \"fulladdress\" : 1 } ). forEach ( function ( doc ) { outputBulk . insert ( doc ); }); outputBulk . execute ();","title":"Make a Copy"},{"location":"Databases/Mongodb/#longer-example","text":"Add a count field to all records function gatherStats () { var start = Date . now (); var inputDB = db . getSiblingDB ( \"inputDB\" ); var inputColl = inputDB . getCollection ( \"inputColl\" ); // debug: inputColl.find( {} ).limit(2).forEach(printjson); outputDB = db . getSiblingDB ( \"outputDB\" ); db = outputDB ; // set current database for the next aggregate step // create temporary collection with count inputColl . aggregate ( [ { $group : { _id : { $toLower : \"$address\" }, count : { $sum : 1 } } }, { $sort : { \"count\" : - 1 } }, { $limit : 100000 }, // limit to 100k addresses with highest count { $out : \"stats\" } ], { allowDiskUse : true } ); // returns { _id, count } where _id is the address var statsColl = outputDB . getCollection ( \"stats\" ); // create output collection var outputColl = outputDB . getCollection ( \"outputColl\" ); var outputBulk = outputColl . initializeUnorderedBulkOp (); var counter = 0 ; var inputCursor = inputColl . find ( {}, {} ); inputCursor . forEach ( function ( doc ) { var statDoc = statsColl . findOne ( { _id : doc . address } ); if ( statDoc ) { doc . count = statDoc . count ; outputBulk . insert ( doc ); counter ++ ; if ( counter % 1000 == 0 ) { outputBulk . execute (); // you have to reset outputBulk = outputColl . initializeUnorderedBulkOp (); } } } ); if ( counter % 1000 > 0 ) outputBulk . execute (); // print the results outputColl . find ({}). sort ({ count : - 1 }). forEach ( printjson ); var end = Date . now (); var duration = ( end - start ) / 1000 ; printjson ( \"Duration: \" + duration + \" seconds\" ); printjson ( \" | DONE | \" ); } gatherStats (); Alternatively move data to memory: var statsDict = {}; // or better Object.create(null); statsColl . find ({}). forEach ( function ( doc ) { statsDict [ doc . _id ] = doc . count } ); // could also use: var statsArray = statsCursor.toArray(); inputCursor . forEach ( function ( doc ) { if ( doc . address in statsDict ) { doc [ \"count\" ] = statsDict [ doc . address ]; outputBulk . insert ( doc ); } }); outputBulk . execute ();","title":"Longer Example"},{"location":"Databases/Redshift/","text":"Redshift Best Practices \u00b6 Smaller node types load data faster Best Practices for data load: 1 file in S3 per slice (instances in RedShift) Compressed using gzip compression File size: 1MB to 1GB compressed COPY from S3 is the fastest COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3 First column of SORTKEY should not be compressed Workflows: move from staging table to production table Make sure to wrap the entire workflow into ONE transaction COMMITs are very expensive in RedShift Disable statistics on staging tables Make sure that the distribution keys match between staging and prod tables Compress your staging tables Do ANALYZE after VACUUM","title":"RedShift"},{"location":"Databases/Redshift/#redshift-best-practices","text":"Smaller node types load data faster Best Practices for data load: 1 file in S3 per slice (instances in RedShift) Compressed using gzip compression File size: 1MB to 1GB compressed COPY from S3 is the fastest COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3 First column of SORTKEY should not be compressed Workflows: move from staging table to production table Make sure to wrap the entire workflow into ONE transaction COMMITs are very expensive in RedShift Disable statistics on staging tables Make sure that the distribution keys match between staging and prod tables Compress your staging tables Do ANALYZE after VACUUM","title":"Redshift Best Practices"},{"location":"Databases/SQL/","text":"SQL Cheatsheet \u00b6 DML: SELECT \u00b6 Filter : SELECT LastName , FirstName , Address FROM Persons WHERE Address IS NULL Like : SELECT * FROM Customers WHERE City LIKE 's%' ; SELECT * FROM Customers WHERE Country LIKE '%land%' ; SELECT * FROM Customers WHERE Country NOT LIKE '%land%' ; Sort : SELECT * FROM Customers ORDER BY Country DESC ; SELECT * FROM Customers ORDER BY Country , CustomerName ; Limit : SELECT TOP number | percent column_name ( s ) FROM table_name ; -- Examples: SELECT TOP 2 * FROM Customers ; SELECT TOP 50 PERCENT * FROM Customers ; Oracle Syntax : SELECT column_name ( s ) FROM table_name WHERE ROWNUM <= number ; Joins : SELECT Customers . CustomerName , Orders . OrderID FROM Customers FULL OUTER JOIN Orders ON Customers . CustomerID = Orders . CustomerID ORDER BY Customers . CustomerName ; Union : SELECT column_name ( s ) FROM table1 UNION SELECT column_name ( s ) FROM table2 ; SELECT column_name ( s ) FROM table1 UNION ALL SELECT column_name ( s ) FROM table2 ; Select Into : SELECT column_name ( s ) INTO newtable [ IN externaldb ] FROM table1 ; Formula : SELECT ProductName , UnitPrice * ( UnitsInStock + ISNULL ( UnitsOnOrder , 0 )) FROM Products DML: INSERT \u00b6 INSERT INTO table_name VALUES ( value1 , value2 , value3 ,...); INSERT INTO table_name ( column1 , column2 , column3 ,...) VALUES ( value1 , value2 , value3 ,...); -- Example: INSERT INTO Customers ( CustomerName , City , Country ) VALUES ( 'Cardinal' , 'Stavanger' , 'Norway' ); Insert from select : INSERT INTO table2 ( column_name ( s )) SELECT column_name ( s ) FROM table1 ; -- Example: INSERT INTO Customers ( CustomerName , Country ) SELECT SupplierName , Country FROM Suppliers WHERE Country = 'Germany' ; DML: UPDATE \u00b6 UPDATE table_name SET column1 = value1 , column2 = value2 ,... WHERE some_column = some_value ; -- Example: UPDATE Customers SET ContactName = 'Alfred Schmidt' , City = 'Hamburg' WHERE CustomerName = 'Alfreds Futterkiste' ; DML: DELETE \u00b6 DELETE FROM table_name WHERE some_column = some_value ; DELETE FROM Customers WHERE CustomerName = 'Alfreds Futterkiste' AND ContactName = 'Maria Anders' ; Databases \u00b6 CREATE DATABASE my_db ; DROP DATABASE my_db ; Tables \u00b6 Create : CREATE TABLE table_name ( column_name1 data_type ( size ), column_name2 data_type ( size ), column_name3 data_type ( size ), .... ); CREATE TABLE table_name ( column_name1 data_type ( size ) constraint_name , column_name2 data_type ( size ) constraint_name , column_name3 data_type ( size ) constraint_name , .... ); -- Examples CREATE TABLE Persons ( P_Id int NOT NULL UNIQUE , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT uc_PersonID UNIQUE ( P_Id , LastName ) ) ALTER TABLE Persons ADD CONSTRAINT uc_PersonID UNIQUE ( P_Id , LastName ) ALTER TABLE Persons DROP CONSTRAINT uc_PersonID Temporary Table : CREATE TABLE # MyTempTable ( cola INT PRIMARY KEY ); INSERT INTO # MyTempTable VALUES ( 1 ); Drop / Truncate : DROP TABLE table_name TRUNCATE TABLE table_name PRIMARY KEY constraint \u00b6 CREATE TABLE Persons ( P_Id int NOT NULL PRIMARY KEY , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT PK_PersonID PRIMARY KEY ( P_Id , LastName ) ) ALTER TABLE Persons ADD CONSTRAINT PK_PersonID PRIMARY KEY ( P_Id , LastName ) ALTER TABLE Persons DROP CONSTRAINT PK_PersonID FOREIGN KEY constraints \u00b6 CREATE TABLE Orders ( O_Id int NOT NULL PRIMARY KEY , OrderNo int NOT NULL , P_Id int FOREIGN KEY REFERENCES Persons ( P_Id ) ) CREATE TABLE Orders ( O_Id int NOT NULL , OrderNo int NOT NULL , P_Id int , PRIMARY KEY ( O_Id ), CONSTRAINT FK_PerOrders FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ) ALTER TABLE Orders ADD FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ALTER TABLE Orders ADD CONSTRAINT fk_PerOrders FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ALTER TABLE Orders DROP CONSTRAINT fk_PerOrders CHECK Constraints \u00b6 CREATE TABLE Persons ( P_Id int NOT NULL CHECK ( P_Id > 0 ), LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT chk_Person CHECK ( P_Id > 0 AND City = 'Sandnes' ) ) ALTER TABLE Persons ADD CONSTRAINT CHK_Person CHECK ( P_Id > 0 AND City = 'Sandnes' ) ALTER TABLE Persons DROP CONSTRAINT CHK_Person DEFAULT Constraints \u00b6 CREATE TABLE Orders ( O_Id int NOT NULL , OrderNo int NOT NULL , P_Id int , OrderDate date DEFAULT GETDATE () ) ALTER TABLE Persons ALTER COLUMN City SET DEFAULT 'SEATTLE' ALTER TABLE Persons ALTER COLUMN City DROP DEFAULT Index \u00b6 CREATE UNIQUE INDEX index_name ON table_name ( column_name ) CREATE INDEX index_name ON table_name ( column_name1 , col_name2 ) -- Example: CREATE INDEX PIndex ON Persons ( LastName , FirstName ) DROP INDEX table_name . index_name -- Example: DROP INDEX IX_ProductVendor_BusinessEntityID ON Purchasing . ProductVendor ; Add / drop / alter column in table \u00b6 ALTER TABLE table_name ADD column_name datatype ALTER TABLE table_name DROP COLUMN column_name ALTER TABLE table_name ALTER COLUMN column_name datatype Autoincrement \u00b6 CREATE TABLE Persons ( ID int IDENTITY ( 1 , 1 ) PRIMARY KEY , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) Example: CREATE TABLE dbo . PurchaseOrderDetail ( PurchaseOrderID int NOT NULL REFERENCES Purchasing . PurchaseOrderHeader ( PurchaseOrderID ), LineNumber smallint NOT NULL , ProductID int NULL REFERENCES Production . Product ( ProductID ), UnitPrice money NULL , OrderQty smallint NULL , ReceivedQty float NULL , RejectedQty float NULL , DueDate datetime NULL , rowguid uniqueidentifier ROWGUIDCOL NOT NULL CONSTRAINT DF_PurchaseOrderDetail_rowguid DEFAULT ( newid ()), ModifiedDate datetime NOT NULL CONSTRAINT DF_PurchaseOrderDetail_ModifiedDate DEFAULT ( getdate ()), LineTotal AS (( UnitPrice * OrderQty )), StockedQty AS (( ReceivedQty - RejectedQty )), CONSTRAINT PK_PurchaseOrderDetail_PurchaseOrderID_LineNumber PRIMARY KEY CLUSTERED ( PurchaseOrderID , LineNumber ) WITH ( IGNORE_DUP_KEY = OFF ) ) ON PRIMARY ; Views \u00b6 CREATE VIEW view_name AS SELECT column_name ( s ) FROM table_name WHERE condition CREATE OR REPLACE VIEW view_name AS SELECT column_name ( s ) FROM table_name WHERE condition DROP VIEW view_name Examples : CREATE VIEW [ Products Above Average Price ] AS SELECT ProductName , UnitPrice FROM Products WHERE UnitPrice > ( SELECT AVG ( UnitPrice ) FROM Products ) SELECT * FROM [ Products Above Average Price ] CREATE VIEW [ Category Sales For 1997 ] AS SELECT DISTINCT CategoryName , Sum ( ProductSales ) AS CategorySales FROM [ Product Sales for 1997 ] GROUP BY CategoryName Dates \u00b6 GETDATE () -- Returns the current date and time DATEPART () -- Returns a single part of a date/time DATEADD () -- Adds or subtracts a specified time interval from a date DATEDIFF () -- Returns the time between two dates CONVERT () -- Displays date/time data in different formats Example : CREATE TABLE Orders ( OrderId int NOT NULL PRIMARY KEY , ProductName varchar ( 50 ) NOT NULL , OrderDate datetime NOT NULL DEFAULT GETDATE () ) SELECT DATEPART ( yyyy , OrderDate ) AS OrderYear , DATEPART ( mm , OrderDate ) AS OrderMonth , DATEPART ( dd , OrderDate ) AS OrderDay , FROM Orders WHERE OrderId = 1 SELECT OrderId , DATEADD ( day , 45 , OrderDate ) AS OrderPayDate FROM Orders SELECT DATEDIFF ( day , '2008-06-05' , '2008-08-05' ) AS DiffDate CONVERT ( VARCHAR ( 19 ), GETDATE ()) CONVERT ( VARCHAR ( 10 ), GETDATE (), 10 ) CONVERT ( VARCHAR ( 10 ), GETDATE (), 110 ) SQL Server Data Types \u00b6 Data type / Description / Storage char(n) Fixed width character string. Maximum 8,000 characters Defined width varchar(n) Variable width character string. Maximum 8,000 characters 2 bytes + number of chars varchar(max) Variable width character string. Maximum 1,073,741,824 characters 2 bytes + number of chars text Variable width character string. Maximum 2GB of text data 4 bytes + number of chars nchar Fixed width Unicode string. Maximum 4,000 characters Defined width x 2 nvarchar Variable width Unicode string. Maximum 4,000 characters nvarchar(max) Variable width Unicode string. Maximum 536,870,912 characters ntext Variable width Unicode string. Maximum 2GB of text data bit Allows 0, 1, or NULL binary(n) Fixed width binary string. Maximum 8,000 bytes varbinary Variable width binary string. Maximum 8,000 bytes varbinary(max) Variable width binary string. Maximum 2GB image Variable width binary string. Maximum 2GB Number types \u00b6 tinyint Allows whole numbers from 0 to 255 1 byte smallint Allows whole numbers between -32,768 and 32,767 2 bytes int Allows whole numbers between -2,147,483,648 and 2,147,483,647 4 bytes bigint Allows whole numbers between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 8 bytes decimal(p,s) Fixed precision and scale numbers. Allows numbers from -10^38 +1 to 10^38. The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. 5-17 bytes numeric(p,s) Fixed precision and scale numbers. Allows numbers from -10^38 +1 to 10^38. The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. 5-17 bytes smallmoney Monetary data from -214,748.3648 to 214,748.3647 4 bytes money Monetary data from -922,337,203,685,477.5808 to 922,337,203,685,477.5807 8 bytes float(n) Floating precision number data from -1.79E + 308 to 1.79E + 308. The n parameter indicates whether the field should hold 4 or 8 bytes. float(24) holds a 4-byte field and float(53) holds an 8-byte field. Default value of n is 53. 4 or 8 bytes real Floating precision number data from -3.40E + 38 to 3.40E + 38 4 bytes Date types \u00b6 datetime From January 1, 1753 to December 31, 9999 with an accuracy of 3.33 milliseconds 8 bytes datetime2 From January 1, 0001 to December 31, 9999 with an accuracy of 100 nanoseconds 6-8 bytes smalldatetime From January 1, 1900 to June 6, 2079 with an accuracy of 1 minute 4 bytes date Store a date only. From January 1, 0001 to December 31, 9999 3 bytes time Store a time only to an accuracy of 100 nanoseconds 3-5 bytes datetimeoffset The same as datetime2 with the addition of a time zone offset 8-10 bytes timestamp Stores a unique number that gets updated every time a row gets created or modified. The timestamp value is based upon an internal clock and does not correspond to real time. Each table may have only one timestamp variable Other data types \u00b6 sql_variant Stores up to 8,000 bytes of data of various data types, except text, ntext, and timestamp uniqueidentifier Stores a globally unique identifier (GUID) xml Stores XML formatted data. Maximum 2GB cursor Stores a reference to a cursor used for database operations table Stores a result-set for later processing SQL Aggregate Functions \u00b6 SQL aggregate functions return a single value, calculated from values in a column. Useful aggregate functions: AVG() - Returns the average value COUNT() - Returns the number of rows TOP 1 - Single sample MAX() - Returns the largest value MIN() - Returns the smallest value SUM() - Returns the sum Examples: SELECT COUNT ( DISTINCT column_name ) FROM table_name ; SELECT TOP 1 column_name FROM table_name ORDER BY column_name DESC ; SELECT column_name , aggregate_function ( column_name ) FROM table_name WHERE column_name operator value GROUP BY column_name ; SELECT Shippers . ShipperName , COUNT ( Orders . OrderID ) AS NumberOfOrders FROM Orders LEFT JOIN Shippers ON Orders . ShipperID = Shippers . ShipperID GROUP BY ShipperName ; SELECT column_name , aggregate_function ( column_name ) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING aggregate_function ( column_name ) operator value ; SELECT Employees . LastName , COUNT ( Orders . OrderID ) AS NumberOfOrders FROM Orders INNER JOIN Employees ON Orders . EmployeeID = Employees . EmployeeID ) GROUP BY LastName HAVING COUNT ( Orders . OrderID ) > 10 ; SQL Scalar functions \u00b6 Converts a field to upper case: SELECT UPPER(column_name) FROM table_name; Converts a field to lower case: SELECT LOWER(column_name) FROM table_name; MID() - Extract characters from a text field LEN() - Returns the length of a text field ROUND() - Rounds a numeric field to the number of decimals specified NOW() - Returns the current system date and time FORMAT() - Formats how a field is to be displayed SELECT ProductName , ROUND ( Price , 0 ) AS RoundedPrice FROM Products ; Variables \u00b6 DECLARE @ myvar char ( 20 ); SET @ myvar = 'This is a test' ; SELECT @ myvar ; Scalar Function \u00b6 CREATE FUNCTION FunctionName ( -- Add the parameters for the function here @ p1 int ) RETURNS int AS BEGIN -- Declare the return variable here DECLARE @ Result int -- Add the T-SQL statements to compute the return value here SELECT @ Result = @ p1 -- Return the result of the function RETURN @ Result END Table Value Function \u00b6 IF OBJECT_ID ( N 'dbo.EmployeeByID' ) IS NOT NULL DROP FUNCTION dbo . EmployeeByID GO CREATE FUNCTION dbo . EmployeeByID ( @ InEmpID int ) RETURNS @ retFindReports TABLE ( -- columns returned by the function EmployeeID int NOT NULL , Name nvarchar ( 255 ) NOT NULL , Title nvarchar ( 50 ) NOT NULL , EmployeeLevel int NOT NULL ) AS -- body of the function BEGIN WITH DirectReports ( Name , Title , EmployeeID , EmployeeLevel , Sort ) AS ( SELECT CONVERT ( varchar ( 255 ), c . FirstName + ' ' + c . LastName ), e . Title , e . EmployeeID , 1 , CONVERT ( varchar ( 255 ), c . FirstName + ' ' + c . LastName ) FROM HumanResources . Employee AS e JOIN Person . Contact AS c ON e . ContactID = c . ContactID WHERE e . EmployeeID = @ InEmpID UNION ALL SELECT CONVERT ( varchar ( 255 ), REPLICATE ( '| ' , EmployeeLevel ) + c . FirstName + ' ' + c . LastName ), e . Title , e . EmployeeID , EmployeeLevel + 1 , CONVERT ( varchar ( 255 ), RTRIM ( Sort ) + '| ' + FirstName + ' ' + LastName ) FROM HumanResources . Employee as e JOIN Person . Contact AS c ON e . ContactID = c . ContactID JOIN DirectReports AS d ON e . ManagerID = d . EmployeeID ) -- copy the required columns to the result of the function INSERT @ retFindReports SELECT EmployeeID , Name , Title , EmployeeLevel FROM DirectReports ORDER BY Sort RETURN END GO Stored Procedure \u00b6 CREATE PROCEDURE ProcedureName -- Add the parameters for the stored procedure here @ p1 int = 0 , @ p2 int = 0 AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON ; -- Insert statements for procedure here SELECT @ p1 , @ p2 END GO Self-join \u00b6 Q. Here's the data in a table 'orders' customer_id order_id order_day 123 27424624 25Dec2011 123 89690900 25Dec2010 797 12131323 25Dec2010 876 67145419 15Dec2011 Could you give me SQL for customers who placed orders on both the days, 25th Dec 2010 and 25th Dec 2011? SELECT o . customer_id , o . order_day FROM orders AS o INNER JOIN orders AS o1 ON o . customer_id = o1 . customer_id WHERE ...","title":"SQL Cheatsheet"},{"location":"Databases/SQL/#sql-cheatsheet","text":"","title":"SQL Cheatsheet"},{"location":"Databases/SQL/#dml-select","text":"Filter : SELECT LastName , FirstName , Address FROM Persons WHERE Address IS NULL Like : SELECT * FROM Customers WHERE City LIKE 's%' ; SELECT * FROM Customers WHERE Country LIKE '%land%' ; SELECT * FROM Customers WHERE Country NOT LIKE '%land%' ; Sort : SELECT * FROM Customers ORDER BY Country DESC ; SELECT * FROM Customers ORDER BY Country , CustomerName ; Limit : SELECT TOP number | percent column_name ( s ) FROM table_name ; -- Examples: SELECT TOP 2 * FROM Customers ; SELECT TOP 50 PERCENT * FROM Customers ; Oracle Syntax : SELECT column_name ( s ) FROM table_name WHERE ROWNUM <= number ; Joins : SELECT Customers . CustomerName , Orders . OrderID FROM Customers FULL OUTER JOIN Orders ON Customers . CustomerID = Orders . CustomerID ORDER BY Customers . CustomerName ; Union : SELECT column_name ( s ) FROM table1 UNION SELECT column_name ( s ) FROM table2 ; SELECT column_name ( s ) FROM table1 UNION ALL SELECT column_name ( s ) FROM table2 ; Select Into : SELECT column_name ( s ) INTO newtable [ IN externaldb ] FROM table1 ; Formula : SELECT ProductName , UnitPrice * ( UnitsInStock + ISNULL ( UnitsOnOrder , 0 )) FROM Products","title":"DML: SELECT"},{"location":"Databases/SQL/#dml-insert","text":"INSERT INTO table_name VALUES ( value1 , value2 , value3 ,...); INSERT INTO table_name ( column1 , column2 , column3 ,...) VALUES ( value1 , value2 , value3 ,...); -- Example: INSERT INTO Customers ( CustomerName , City , Country ) VALUES ( 'Cardinal' , 'Stavanger' , 'Norway' ); Insert from select : INSERT INTO table2 ( column_name ( s )) SELECT column_name ( s ) FROM table1 ; -- Example: INSERT INTO Customers ( CustomerName , Country ) SELECT SupplierName , Country FROM Suppliers WHERE Country = 'Germany' ;","title":"DML: INSERT"},{"location":"Databases/SQL/#dml-update","text":"UPDATE table_name SET column1 = value1 , column2 = value2 ,... WHERE some_column = some_value ; -- Example: UPDATE Customers SET ContactName = 'Alfred Schmidt' , City = 'Hamburg' WHERE CustomerName = 'Alfreds Futterkiste' ;","title":"DML: UPDATE"},{"location":"Databases/SQL/#dml-delete","text":"DELETE FROM table_name WHERE some_column = some_value ; DELETE FROM Customers WHERE CustomerName = 'Alfreds Futterkiste' AND ContactName = 'Maria Anders' ;","title":"DML: DELETE"},{"location":"Databases/SQL/#databases","text":"CREATE DATABASE my_db ; DROP DATABASE my_db ;","title":"Databases"},{"location":"Databases/SQL/#tables","text":"Create : CREATE TABLE table_name ( column_name1 data_type ( size ), column_name2 data_type ( size ), column_name3 data_type ( size ), .... ); CREATE TABLE table_name ( column_name1 data_type ( size ) constraint_name , column_name2 data_type ( size ) constraint_name , column_name3 data_type ( size ) constraint_name , .... ); -- Examples CREATE TABLE Persons ( P_Id int NOT NULL UNIQUE , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT uc_PersonID UNIQUE ( P_Id , LastName ) ) ALTER TABLE Persons ADD CONSTRAINT uc_PersonID UNIQUE ( P_Id , LastName ) ALTER TABLE Persons DROP CONSTRAINT uc_PersonID Temporary Table : CREATE TABLE # MyTempTable ( cola INT PRIMARY KEY ); INSERT INTO # MyTempTable VALUES ( 1 ); Drop / Truncate : DROP TABLE table_name TRUNCATE TABLE table_name","title":"Tables"},{"location":"Databases/SQL/#primary-key-constraint","text":"CREATE TABLE Persons ( P_Id int NOT NULL PRIMARY KEY , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT PK_PersonID PRIMARY KEY ( P_Id , LastName ) ) ALTER TABLE Persons ADD CONSTRAINT PK_PersonID PRIMARY KEY ( P_Id , LastName ) ALTER TABLE Persons DROP CONSTRAINT PK_PersonID","title":"PRIMARY KEY constraint"},{"location":"Databases/SQL/#foreign-key-constraints","text":"CREATE TABLE Orders ( O_Id int NOT NULL PRIMARY KEY , OrderNo int NOT NULL , P_Id int FOREIGN KEY REFERENCES Persons ( P_Id ) ) CREATE TABLE Orders ( O_Id int NOT NULL , OrderNo int NOT NULL , P_Id int , PRIMARY KEY ( O_Id ), CONSTRAINT FK_PerOrders FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ) ALTER TABLE Orders ADD FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ALTER TABLE Orders ADD CONSTRAINT fk_PerOrders FOREIGN KEY ( P_Id ) REFERENCES Persons ( P_Id ) ALTER TABLE Orders DROP CONSTRAINT fk_PerOrders","title":"FOREIGN KEY constraints"},{"location":"Databases/SQL/#check-constraints","text":"CREATE TABLE Persons ( P_Id int NOT NULL CHECK ( P_Id > 0 ), LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) CREATE TABLE Persons ( P_Id int NOT NULL , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ), CONSTRAINT chk_Person CHECK ( P_Id > 0 AND City = 'Sandnes' ) ) ALTER TABLE Persons ADD CONSTRAINT CHK_Person CHECK ( P_Id > 0 AND City = 'Sandnes' ) ALTER TABLE Persons DROP CONSTRAINT CHK_Person","title":"CHECK Constraints"},{"location":"Databases/SQL/#default-constraints","text":"CREATE TABLE Orders ( O_Id int NOT NULL , OrderNo int NOT NULL , P_Id int , OrderDate date DEFAULT GETDATE () ) ALTER TABLE Persons ALTER COLUMN City SET DEFAULT 'SEATTLE' ALTER TABLE Persons ALTER COLUMN City DROP DEFAULT","title":"DEFAULT Constraints"},{"location":"Databases/SQL/#index","text":"CREATE UNIQUE INDEX index_name ON table_name ( column_name ) CREATE INDEX index_name ON table_name ( column_name1 , col_name2 ) -- Example: CREATE INDEX PIndex ON Persons ( LastName , FirstName ) DROP INDEX table_name . index_name -- Example: DROP INDEX IX_ProductVendor_BusinessEntityID ON Purchasing . ProductVendor ;","title":"Index"},{"location":"Databases/SQL/#add--drop--alter-column-in-table","text":"ALTER TABLE table_name ADD column_name datatype ALTER TABLE table_name DROP COLUMN column_name ALTER TABLE table_name ALTER COLUMN column_name datatype","title":"Add / drop / alter column in table"},{"location":"Databases/SQL/#autoincrement","text":"CREATE TABLE Persons ( ID int IDENTITY ( 1 , 1 ) PRIMARY KEY , LastName varchar ( 255 ) NOT NULL , FirstName varchar ( 255 ), Address varchar ( 255 ), City varchar ( 255 ) ) Example: CREATE TABLE dbo . PurchaseOrderDetail ( PurchaseOrderID int NOT NULL REFERENCES Purchasing . PurchaseOrderHeader ( PurchaseOrderID ), LineNumber smallint NOT NULL , ProductID int NULL REFERENCES Production . Product ( ProductID ), UnitPrice money NULL , OrderQty smallint NULL , ReceivedQty float NULL , RejectedQty float NULL , DueDate datetime NULL , rowguid uniqueidentifier ROWGUIDCOL NOT NULL CONSTRAINT DF_PurchaseOrderDetail_rowguid DEFAULT ( newid ()), ModifiedDate datetime NOT NULL CONSTRAINT DF_PurchaseOrderDetail_ModifiedDate DEFAULT ( getdate ()), LineTotal AS (( UnitPrice * OrderQty )), StockedQty AS (( ReceivedQty - RejectedQty )), CONSTRAINT PK_PurchaseOrderDetail_PurchaseOrderID_LineNumber PRIMARY KEY CLUSTERED ( PurchaseOrderID , LineNumber ) WITH ( IGNORE_DUP_KEY = OFF ) ) ON PRIMARY ;","title":"Autoincrement"},{"location":"Databases/SQL/#views","text":"CREATE VIEW view_name AS SELECT column_name ( s ) FROM table_name WHERE condition CREATE OR REPLACE VIEW view_name AS SELECT column_name ( s ) FROM table_name WHERE condition DROP VIEW view_name Examples : CREATE VIEW [ Products Above Average Price ] AS SELECT ProductName , UnitPrice FROM Products WHERE UnitPrice > ( SELECT AVG ( UnitPrice ) FROM Products ) SELECT * FROM [ Products Above Average Price ] CREATE VIEW [ Category Sales For 1997 ] AS SELECT DISTINCT CategoryName , Sum ( ProductSales ) AS CategorySales FROM [ Product Sales for 1997 ] GROUP BY CategoryName","title":"Views"},{"location":"Databases/SQL/#dates","text":"GETDATE () -- Returns the current date and time DATEPART () -- Returns a single part of a date/time DATEADD () -- Adds or subtracts a specified time interval from a date DATEDIFF () -- Returns the time between two dates CONVERT () -- Displays date/time data in different formats Example : CREATE TABLE Orders ( OrderId int NOT NULL PRIMARY KEY , ProductName varchar ( 50 ) NOT NULL , OrderDate datetime NOT NULL DEFAULT GETDATE () ) SELECT DATEPART ( yyyy , OrderDate ) AS OrderYear , DATEPART ( mm , OrderDate ) AS OrderMonth , DATEPART ( dd , OrderDate ) AS OrderDay , FROM Orders WHERE OrderId = 1 SELECT OrderId , DATEADD ( day , 45 , OrderDate ) AS OrderPayDate FROM Orders SELECT DATEDIFF ( day , '2008-06-05' , '2008-08-05' ) AS DiffDate CONVERT ( VARCHAR ( 19 ), GETDATE ()) CONVERT ( VARCHAR ( 10 ), GETDATE (), 10 ) CONVERT ( VARCHAR ( 10 ), GETDATE (), 110 )","title":"Dates"},{"location":"Databases/SQL/#sql-server-data-types","text":"Data type / Description / Storage char(n) Fixed width character string. Maximum 8,000 characters Defined width varchar(n) Variable width character string. Maximum 8,000 characters 2 bytes + number of chars varchar(max) Variable width character string. Maximum 1,073,741,824 characters 2 bytes + number of chars text Variable width character string. Maximum 2GB of text data 4 bytes + number of chars nchar Fixed width Unicode string. Maximum 4,000 characters Defined width x 2 nvarchar Variable width Unicode string. Maximum 4,000 characters nvarchar(max) Variable width Unicode string. Maximum 536,870,912 characters ntext Variable width Unicode string. Maximum 2GB of text data bit Allows 0, 1, or NULL binary(n) Fixed width binary string. Maximum 8,000 bytes varbinary Variable width binary string. Maximum 8,000 bytes varbinary(max) Variable width binary string. Maximum 2GB image Variable width binary string. Maximum 2GB","title":"SQL Server Data Types"},{"location":"Databases/SQL/#number-types","text":"tinyint Allows whole numbers from 0 to 255 1 byte smallint Allows whole numbers between -32,768 and 32,767 2 bytes int Allows whole numbers between -2,147,483,648 and 2,147,483,647 4 bytes bigint Allows whole numbers between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 8 bytes decimal(p,s) Fixed precision and scale numbers. Allows numbers from -10^38 +1 to 10^38. The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. 5-17 bytes numeric(p,s) Fixed precision and scale numbers. Allows numbers from -10^38 +1 to 10^38. The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. 5-17 bytes smallmoney Monetary data from -214,748.3648 to 214,748.3647 4 bytes money Monetary data from -922,337,203,685,477.5808 to 922,337,203,685,477.5807 8 bytes float(n) Floating precision number data from -1.79E + 308 to 1.79E + 308. The n parameter indicates whether the field should hold 4 or 8 bytes. float(24) holds a 4-byte field and float(53) holds an 8-byte field. Default value of n is 53. 4 or 8 bytes real Floating precision number data from -3.40E + 38 to 3.40E + 38 4 bytes","title":"Number types"},{"location":"Databases/SQL/#date-types","text":"datetime From January 1, 1753 to December 31, 9999 with an accuracy of 3.33 milliseconds 8 bytes datetime2 From January 1, 0001 to December 31, 9999 with an accuracy of 100 nanoseconds 6-8 bytes smalldatetime From January 1, 1900 to June 6, 2079 with an accuracy of 1 minute 4 bytes date Store a date only. From January 1, 0001 to December 31, 9999 3 bytes time Store a time only to an accuracy of 100 nanoseconds 3-5 bytes datetimeoffset The same as datetime2 with the addition of a time zone offset 8-10 bytes timestamp Stores a unique number that gets updated every time a row gets created or modified. The timestamp value is based upon an internal clock and does not correspond to real time. Each table may have only one timestamp variable","title":"Date types"},{"location":"Databases/SQL/#other-data-types","text":"sql_variant Stores up to 8,000 bytes of data of various data types, except text, ntext, and timestamp uniqueidentifier Stores a globally unique identifier (GUID) xml Stores XML formatted data. Maximum 2GB cursor Stores a reference to a cursor used for database operations table Stores a result-set for later processing","title":"Other data types"},{"location":"Databases/SQL/#sql-aggregate-functions","text":"SQL aggregate functions return a single value, calculated from values in a column. Useful aggregate functions: AVG() - Returns the average value COUNT() - Returns the number of rows TOP 1 - Single sample MAX() - Returns the largest value MIN() - Returns the smallest value SUM() - Returns the sum Examples: SELECT COUNT ( DISTINCT column_name ) FROM table_name ; SELECT TOP 1 column_name FROM table_name ORDER BY column_name DESC ; SELECT column_name , aggregate_function ( column_name ) FROM table_name WHERE column_name operator value GROUP BY column_name ; SELECT Shippers . ShipperName , COUNT ( Orders . OrderID ) AS NumberOfOrders FROM Orders LEFT JOIN Shippers ON Orders . ShipperID = Shippers . ShipperID GROUP BY ShipperName ; SELECT column_name , aggregate_function ( column_name ) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING aggregate_function ( column_name ) operator value ; SELECT Employees . LastName , COUNT ( Orders . OrderID ) AS NumberOfOrders FROM Orders INNER JOIN Employees ON Orders . EmployeeID = Employees . EmployeeID ) GROUP BY LastName HAVING COUNT ( Orders . OrderID ) > 10 ;","title":"SQL Aggregate Functions"},{"location":"Databases/SQL/#sql-scalar-functions","text":"Converts a field to upper case: SELECT UPPER(column_name) FROM table_name; Converts a field to lower case: SELECT LOWER(column_name) FROM table_name; MID() - Extract characters from a text field LEN() - Returns the length of a text field ROUND() - Rounds a numeric field to the number of decimals specified NOW() - Returns the current system date and time FORMAT() - Formats how a field is to be displayed SELECT ProductName , ROUND ( Price , 0 ) AS RoundedPrice FROM Products ;","title":"SQL Scalar functions"},{"location":"Databases/SQL/#variables","text":"DECLARE @ myvar char ( 20 ); SET @ myvar = 'This is a test' ; SELECT @ myvar ;","title":"Variables"},{"location":"Databases/SQL/#scalar-function","text":"CREATE FUNCTION FunctionName ( -- Add the parameters for the function here @ p1 int ) RETURNS int AS BEGIN -- Declare the return variable here DECLARE @ Result int -- Add the T-SQL statements to compute the return value here SELECT @ Result = @ p1 -- Return the result of the function RETURN @ Result END","title":"Scalar Function"},{"location":"Databases/SQL/#table-value-function","text":"IF OBJECT_ID ( N 'dbo.EmployeeByID' ) IS NOT NULL DROP FUNCTION dbo . EmployeeByID GO CREATE FUNCTION dbo . EmployeeByID ( @ InEmpID int ) RETURNS @ retFindReports TABLE ( -- columns returned by the function EmployeeID int NOT NULL , Name nvarchar ( 255 ) NOT NULL , Title nvarchar ( 50 ) NOT NULL , EmployeeLevel int NOT NULL ) AS -- body of the function BEGIN WITH DirectReports ( Name , Title , EmployeeID , EmployeeLevel , Sort ) AS ( SELECT CONVERT ( varchar ( 255 ), c . FirstName + ' ' + c . LastName ), e . Title , e . EmployeeID , 1 , CONVERT ( varchar ( 255 ), c . FirstName + ' ' + c . LastName ) FROM HumanResources . Employee AS e JOIN Person . Contact AS c ON e . ContactID = c . ContactID WHERE e . EmployeeID = @ InEmpID UNION ALL SELECT CONVERT ( varchar ( 255 ), REPLICATE ( '| ' , EmployeeLevel ) + c . FirstName + ' ' + c . LastName ), e . Title , e . EmployeeID , EmployeeLevel + 1 , CONVERT ( varchar ( 255 ), RTRIM ( Sort ) + '| ' + FirstName + ' ' + LastName ) FROM HumanResources . Employee as e JOIN Person . Contact AS c ON e . ContactID = c . ContactID JOIN DirectReports AS d ON e . ManagerID = d . EmployeeID ) -- copy the required columns to the result of the function INSERT @ retFindReports SELECT EmployeeID , Name , Title , EmployeeLevel FROM DirectReports ORDER BY Sort RETURN END GO","title":"Table Value Function"},{"location":"Databases/SQL/#stored-procedure","text":"CREATE PROCEDURE ProcedureName -- Add the parameters for the stored procedure here @ p1 int = 0 , @ p2 int = 0 AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON ; -- Insert statements for procedure here SELECT @ p1 , @ p2 END GO","title":"Stored Procedure"},{"location":"Databases/SQL/#self-join","text":"Q. Here's the data in a table 'orders' customer_id order_id order_day 123 27424624 25Dec2011 123 89690900 25Dec2010 797 12131323 25Dec2010 876 67145419 15Dec2011 Could you give me SQL for customers who placed orders on both the days, 25th Dec 2010 and 25th Dec 2011? SELECT o . customer_id , o . order_day FROM orders AS o INNER JOIN orders AS o1 ON o . customer_id = o1 . customer_id WHERE ...","title":"Self-join"},{"location":"DevOps/CloudFormation/","text":"DevOps Philosophy \u00b6 Why we use Terraform and not Chef, Puppet, Ansible, SaltStack, or CloudFormation Tools \u00b6 AWS CLI cloudformation aws cloudformation validate-template boto3 cloudformation YAML \u00b6 YAML Cheatsheet YAML Cheatsheet 2 YAML notation for folded text: > data : > Wrapped text will be folded into a single paragraph Blank lines denote paragraph breaks Sample Templates \u00b6 Templates for the US East (Northern Virginia) Region AWSlabs on GitHub - Startup kit templates - AWS CloudFormation Sample Templates Cloudonaut Templates Free Templates for AWS CloudFormation (Cloudonaut) Deploying Microservices with Amazon ECS, AWS CloudFormation, and an Application Load Balancer Template Basics \u00b6 Template Basics Template Anatomy --- AWSTemplateFormatVersion : \"version date\" Description : String Metadata : template metadata Parameters : set of parameters Mappings : set of mappings Conditions : set of conditions Transform : set of transforms Resources : set of resources Outputs : set of outputs With examples: --- AWSTemplateFormatVersion : \"2010-09-09\" Description : > Here are some details about the template. Metadata : Instances : Description : \"Information about the instances\" Databases : Description : \"Information about the databases\" Parameters : InstanceTypeParameter : Type : String # String, Number, List, CommaDelimitedList e.g. \"test,dev,prod\", or an AWS-specific types such as Amazon EC2 key pair names and VPC IDs. Default : t2.micro AllowedValues : - t2.micro - m1.small Description : Enter t2.micro or m1.small. Default is t2.micro. # AllowedPattern: \"[A-Za-z0-9]+\" # A regular expression that represents the patterns you want to allow for String types. # ConstraintDescription: Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+ # MinLength: 2 # for String # MaxLength: 10 # MinValue: 0 # for Number types. # MaxValue: 100 # NoEcho: True Mappings : RegionMap : us-east-1 : \"32\" : \"ami-6411e20d\" us-west-1 : \"32\" : \"ami-c9c7978c\" eu-west-1 : \"32\" : \"ami-37c2f643\" ap-southeast-1 : \"32\" : \"ami-66f28c34\" ap-northeast-1 : \"32\" : \"ami-9c03a89d\" Conditions : CreateProdResources : !Equals [ !Ref EnvType , prod ] Transform : set of transforms Resources : Ec2Instance : Type : AWS::EC2::Instance Properties : InstanceType : Ref : InstanceTypeParameter # reference to parameter above ImageId : ami-2f726546 Outputs : VolumeId : Condition : CreateProdResources Value : !Ref NewVolume The Ref function can refer to input parameters that are specified at stack creation time. Examples \u00b6 S3 \u00b6 Resources : HelloBucket : Type : AWS::S3::Bucket # AWS::ProductIdentifier::ResourceType EC2 \u00b6 Resources : Ec2Instance : Type : AWS::EC2::Instance Properties : SecurityGroups : - Ref : InstanceSecurityGroup KeyName : mykey ImageId : '' InstanceSecurityGroup : Type : AWS::EC2::SecurityGroup Properties : GroupDescription : Enable SSH access via port 22 SecurityGroupIngress : - IpProtocol : tcp FromPort : '22' ToPort : '22' CidrIp : 0.0.0.0/0","title":"CloudFormation Basics"},{"location":"DevOps/CloudFormation/#devops-philosophy","text":"Why we use Terraform and not Chef, Puppet, Ansible, SaltStack, or CloudFormation","title":"DevOps Philosophy"},{"location":"DevOps/CloudFormation/#tools","text":"AWS CLI cloudformation aws cloudformation validate-template boto3 cloudformation","title":"Tools"},{"location":"DevOps/CloudFormation/#yaml","text":"YAML Cheatsheet YAML Cheatsheet 2 YAML notation for folded text: > data : > Wrapped text will be folded into a single paragraph Blank lines denote paragraph breaks","title":"YAML"},{"location":"DevOps/CloudFormation/#sample-templates","text":"Templates for the US East (Northern Virginia) Region AWSlabs on GitHub - Startup kit templates - AWS CloudFormation Sample Templates Cloudonaut Templates Free Templates for AWS CloudFormation (Cloudonaut) Deploying Microservices with Amazon ECS, AWS CloudFormation, and an Application Load Balancer","title":"Sample Templates"},{"location":"DevOps/CloudFormation/#template-basics","text":"Template Basics Template Anatomy --- AWSTemplateFormatVersion : \"version date\" Description : String Metadata : template metadata Parameters : set of parameters Mappings : set of mappings Conditions : set of conditions Transform : set of transforms Resources : set of resources Outputs : set of outputs With examples: --- AWSTemplateFormatVersion : \"2010-09-09\" Description : > Here are some details about the template. Metadata : Instances : Description : \"Information about the instances\" Databases : Description : \"Information about the databases\" Parameters : InstanceTypeParameter : Type : String # String, Number, List, CommaDelimitedList e.g. \"test,dev,prod\", or an AWS-specific types such as Amazon EC2 key pair names and VPC IDs. Default : t2.micro AllowedValues : - t2.micro - m1.small Description : Enter t2.micro or m1.small. Default is t2.micro. # AllowedPattern: \"[A-Za-z0-9]+\" # A regular expression that represents the patterns you want to allow for String types. # ConstraintDescription: Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+ # MinLength: 2 # for String # MaxLength: 10 # MinValue: 0 # for Number types. # MaxValue: 100 # NoEcho: True Mappings : RegionMap : us-east-1 : \"32\" : \"ami-6411e20d\" us-west-1 : \"32\" : \"ami-c9c7978c\" eu-west-1 : \"32\" : \"ami-37c2f643\" ap-southeast-1 : \"32\" : \"ami-66f28c34\" ap-northeast-1 : \"32\" : \"ami-9c03a89d\" Conditions : CreateProdResources : !Equals [ !Ref EnvType , prod ] Transform : set of transforms Resources : Ec2Instance : Type : AWS::EC2::Instance Properties : InstanceType : Ref : InstanceTypeParameter # reference to parameter above ImageId : ami-2f726546 Outputs : VolumeId : Condition : CreateProdResources Value : !Ref NewVolume The Ref function can refer to input parameters that are specified at stack creation time.","title":"Template Basics"},{"location":"DevOps/CloudFormation/#examples","text":"","title":"Examples"},{"location":"DevOps/CloudFormation/#s3","text":"Resources : HelloBucket : Type : AWS::S3::Bucket # AWS::ProductIdentifier::ResourceType","title":"S3"},{"location":"DevOps/CloudFormation/#ec2","text":"Resources : Ec2Instance : Type : AWS::EC2::Instance Properties : SecurityGroups : - Ref : InstanceSecurityGroup KeyName : mykey ImageId : '' InstanceSecurityGroup : Type : AWS::EC2::SecurityGroup Properties : GroupDescription : Enable SSH access via port 22 SecurityGroupIngress : - IpProtocol : tcp FromPort : '22' ToPort : '22' CidrIp : 0.0.0.0/0","title":"EC2"},{"location":"DevOps/Git/","text":"Git Cheatsheets \u00b6 Graphical git cheatsheet Git basic commands Git cheatsheet (visual) Git cheatsheet (interactive) Git full documentation Repo hosting: * BitBucket * GitHub Common Commands \u00b6 Create a new Git repository in current directory: git init Or create an empty Git repository in the specified directory: git init Or copy an existing Git repository: git clone Clone the repository located at into the folder called on the local machine: git clone git clone username@host:/path/to/repository Global Configuration: $ git config --global user.name \"Firstname Lastname\" $ git config --global user.email \"your_email@youremail.com\" Stage all changes in for the next commit: git add Or stage all changes in for the next commit: git add # usually '.' for current directory Commit the staged snapshot to the project history: git commit # interactive git commit -m \"\" Or add and commit all in one: git commit -am \"message\" Fix up the most recent commit (don't do that if shared history): git commit --amend List which files are staged, unstaged, and untracked: git status git status -s # short format Show file diff: git diff # git diff by itself doesn\u2019t show all changes made since your last commit \u2013 only changes that are still unstaged. git diff --staged # Shows file differences between staging and the last file version Open GUI: git gui Displays committed snapshots: git log -n git log --graph --decorate --oneline Checking out commits, and checking out branches: git checkout # Return to commit git checkout master # Return to the master branch (or whatever branch we choose) Check out a previous version of a file: git checkout # Check out the version of the file from the selected commit git checkout HEAD hello.py # Check out the most recent version Branches \u00b6 Branches are just pointers to commits. List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch): git branch Create a new branch called . git branch This does not check out the new branch. You need: git checkout Or direcly create-and-check out . git checkout -b Safe delete the branch: git branch -d Merge the specified branch into the current branch: git merge Undo any undesired changes Generate a new commit that undoes all of the changes introduced in , then apply it to the current branch git revert git revert undoes a single commit \u2014 it does not \u201crevert\u201d back to the previous state of a project by removing all subsequent commits. Reset (dangerous method - erases history): git reset List the remote connections you have to other repositories. git remote -v Create a new connection / delete a connection to a remote repository. git remote add # often \"origin\" git remote rm # delete Fetch the specified remote\u2019s copy of the current branch and immediately merge it into the local copy. This is the same as git fetch followed by git merge origin/ . git pull Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits. git pull --rebase Transfer commits from your local repository to a remote repo. git push Pushes the current branch to the remote server and links the local branch to the remote so next time you can do git pull or git push . git push -u origin Typical Workflows \u00b6 Clone a Repo \u00b6 $ mkdir repos $ cd ~/repos $ git clone https:// $ ls -al Add a change in the working directory to the staging area \u00b6 $ git status $ git add README -A , --all finds new files as well as staging modified content and removing files that are no longer in the working tree. $ git add -A $ git commit -m \"Add repo instructions\" $ git push -u origin master $ git pull $ ssh -p 2222 user@domain.com Short-lived topic branches \u00b6 Start a new feature: git checkout -b new-feature master Edit some files: git add git commit -m \"Start a feature\" Edit some files git add git commit -m \"Finish a feature\" Merge in the new-feature branch git checkout master git merge new-feature git branch -d new-feature Push and pull from a centralized repo \u00b6 To push the master branch to the central repo: git push origin master If local history has diverged from the central repository, Git will refuse the request. git pull --rebase origin master Sync my local repo with the remote repo \u00b6 git pull origin master git add filename.xyz git commit . -m \u201ccomment\u201d git push origin master Create a central Repo \u00b6 The --bare flag creates a repository that doesn\u2019t have a working directory, making it impossible to edit files and commit changes in that repository. Central repositories should always be created as bare repositories because pushing branches to a non-bare repository has the potential to overwrite changes. $ git init --bare foobar.git $ git rev-parse --show-toplevel # print top-level directory $ git rev-parse --git-dir # print .git directory name","title":"Git Cheatsheet"},{"location":"DevOps/Git/#git-cheatsheets","text":"Graphical git cheatsheet Git basic commands Git cheatsheet (visual) Git cheatsheet (interactive) Git full documentation Repo hosting: * BitBucket * GitHub","title":"Git Cheatsheets"},{"location":"DevOps/Git/#common-commands","text":"Create a new Git repository in current directory: git init Or create an empty Git repository in the specified directory: git init Or copy an existing Git repository: git clone Clone the repository located at into the folder called on the local machine: git clone git clone username@host:/path/to/repository Global Configuration: $ git config --global user.name \"Firstname Lastname\" $ git config --global user.email \"your_email@youremail.com\" Stage all changes in for the next commit: git add Or stage all changes in for the next commit: git add # usually '.' for current directory Commit the staged snapshot to the project history: git commit # interactive git commit -m \"\" Or add and commit all in one: git commit -am \"message\" Fix up the most recent commit (don't do that if shared history): git commit --amend List which files are staged, unstaged, and untracked: git status git status -s # short format Show file diff: git diff # git diff by itself doesn\u2019t show all changes made since your last commit \u2013 only changes that are still unstaged. git diff --staged # Shows file differences between staging and the last file version Open GUI: git gui Displays committed snapshots: git log -n git log --graph --decorate --oneline Checking out commits, and checking out branches: git checkout # Return to commit git checkout master # Return to the master branch (or whatever branch we choose) Check out a previous version of a file: git checkout # Check out the version of the file from the selected commit git checkout HEAD hello.py # Check out the most recent version","title":"Common Commands"},{"location":"DevOps/Git/#branches","text":"Branches are just pointers to commits. List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch): git branch Create a new branch called . git branch This does not check out the new branch. You need: git checkout Or direcly create-and-check out . git checkout -b Safe delete the branch: git branch -d Merge the specified branch into the current branch: git merge Undo any undesired changes Generate a new commit that undoes all of the changes introduced in , then apply it to the current branch git revert git revert undoes a single commit \u2014 it does not \u201crevert\u201d back to the previous state of a project by removing all subsequent commits. Reset (dangerous method - erases history): git reset List the remote connections you have to other repositories. git remote -v Create a new connection / delete a connection to a remote repository. git remote add # often \"origin\" git remote rm # delete Fetch the specified remote\u2019s copy of the current branch and immediately merge it into the local copy. This is the same as git fetch followed by git merge origin/ . git pull Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits. git pull --rebase Transfer commits from your local repository to a remote repo. git push Pushes the current branch to the remote server and links the local branch to the remote so next time you can do git pull or git push . git push -u origin ","title":"Branches"},{"location":"DevOps/Git/#typical-workflows","text":"","title":"Typical Workflows"},{"location":"DevOps/Git/#clone-a-repo","text":"$ mkdir repos $ cd ~/repos $ git clone https:// $ ls -al ","title":"Clone a Repo"},{"location":"DevOps/Git/#add-a-change-in-the-working-directory-to-the-staging-area","text":"$ git status $ git add README -A , --all finds new files as well as staging modified content and removing files that are no longer in the working tree. $ git add -A $ git commit -m \"Add repo instructions\" $ git push -u origin master $ git pull $ ssh -p 2222 user@domain.com","title":"Add a change in the working directory to the staging area"},{"location":"DevOps/Git/#short-lived-topic-branches","text":"Start a new feature: git checkout -b new-feature master Edit some files: git add git commit -m \"Start a feature\" Edit some files git add git commit -m \"Finish a feature\" Merge in the new-feature branch git checkout master git merge new-feature git branch -d new-feature","title":"Short-lived topic branches"},{"location":"DevOps/Git/#push-and-pull-from-a-centralized-repo","text":"To push the master branch to the central repo: git push origin master If local history has diverged from the central repository, Git will refuse the request. git pull --rebase origin master","title":"Push and pull from a centralized repo"},{"location":"DevOps/Git/#sync-my-local-repo-with-the-remote-repo","text":"git pull origin master git add filename.xyz git commit . -m \u201ccomment\u201d git push origin master","title":"Sync my local repo with the remote repo"},{"location":"DevOps/Git/#create-a-central-repo","text":"The --bare flag creates a repository that doesn\u2019t have a working directory, making it impossible to edit files and commit changes in that repository. Central repositories should always be created as bare repositories because pushing branches to a non-bare repository has the potential to overwrite changes. $ git init --bare foobar.git $ git rev-parse --show-toplevel # print top-level directory $ git rev-parse --git-dir # print .git directory name","title":"Create a central Repo"},{"location":"DevOps/Orchestrator_Scheduler/","text":"Orchestrators / Schedulers \u00b6 Tools to build complex pipelines of batch jobs. They handle dependency resolution, workflow management, visualization. Links \u00b6 Luigi vs Airflow vs Pinball Airflow Documentation Luigi Petabyte-Scale Data Pipelines with Docker, Luigi and Elastic Spot Instances Snowplow","title":"Orchestrators / Schedulers"},{"location":"DevOps/Orchestrator_Scheduler/#orchestrators--schedulers","text":"Tools to build complex pipelines of batch jobs. They handle dependency resolution, workflow management, visualization.","title":"Orchestrators / Schedulers"},{"location":"DevOps/Orchestrator_Scheduler/#links","text":"Luigi vs Airflow vs Pinball Airflow Documentation Luigi Petabyte-Scale Data Pipelines with Docker, Luigi and Elastic Spot Instances Snowplow","title":"Links"},{"location":"Java/Gradle/","text":"Gradle \u00b6 Install \u00b6 In Windows 10 WSL, install sdkman sudo apt install zip curl -s \"https://get.sdkman.io\" | bash source \" $HOME /.sdkman/bin/sdkman-init.sh\" sdk version Install gradle sdk install gradle gradle -v Create a gradle project (for Java) cd /mnt/d/code/gradle gradle init --type java-application You can now use ./gradlew or gradlew.bat in the project folder Usage with Java \u00b6 Example for the JVM Common commands \u00b6 ./gradlew tasks in your project directory lists which tasks you can run in your project, such as building or running your code. ./gradlew projects ./gradlew properties Most commonly used Java tasks: ./gradlew build will compile your project's code into a /build folder. ./gradlew run will run the compiled code in your build folder. ./gradlew clean will purge that build folder. ./gradlew test will execute unit tests without building or running your code again. Build process \u00b6 Gradle launches as a new JVM process It parses the gradle.properties file and configures Gradle accordingly Next, it creates a Settings instance for the build Then, it evaluates the settings.gradle file against the Settings object It creates a hierarchy of Projects, based on the configured Settings object Finally, it executes each build.gradle file against its project In case of a multi-project build, we'd probably have multiple different build.gradle files, one for each project. The build.gradle file is executed against a Project instance, with one Project instance created per subproject. Groovy DSL \u00b6 Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application. Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository. Tasks \u00b6 Tasks are snippets that we can run directly from the command line in our project directory via ./gradlew [TASK_NAME] ./gradlew copy task copy ( type: Copy , group: \"Custom\" , description: \"Copies sources to the dest directory\" ) { from \"src\" into \"dest\" } // accessing task properties println copy . destinationDir println project . copy . destinationDir task ( 'copy2' , type: Copy ) { description 'Copies the resource directory to the target directory.' from ( file ( 'src' )) into ( buildDir ) include ( '**/*.txt' , '**/*.xml' , '**/*.properties' ) timeout = Duration . ofMillis ( 50000 ) } task hello { group = 'Worthless tasks' description = 'An utterly useless task' // extra (custom) properties ext . myProperty = \"myValue\" doLast { println 'Hello world!' } } // API call hello . doLast { println \"Greetings from the $hello.name task.\" // accessing task property in interpolated string } hello . configure { doLast { println 'Hello again' } } task next { dependsOn hello // or 'hello' if lazy initialized - task dependency doLast { println hello . myProperty } } ./gradlew -q hello ./gradlew -q next // dynamic tasks 4 . times { counter -> task \"task$counter\" { doLast { println \"I'm task number $counter\" } } } // default tasks defaultTasks 'task0' , 'task1' import org.apache.commons.codec.binary.Base64 // dependencies for the build script buildscript { repositories { mavenCentral () } dependencies { classpath group: 'commons-codec' , name: 'commons-codec' , version: '1.2' } } task encode { doLast { // using the build script dependencies def byte [] encodedString = new Base64 (). encode ( 'hello world\\n' . getBytes ()) println new String ( encodedString ) } } // you can also declare methods File [] fileList ( String dir ) { file ( dir ). listFiles ({ file -> file . isFile () } as FileFilter ). sort () } Plugins \u00b6 https://plugins.gradle.org/ plugins { id \"base\" } Essential plugins for Java: plugins { id 'java' id 'application' } apply plugin: 'application' Dependencies and repositories \u00b6 repositories { jcenter () // or mavenCentral() } dependencies { implementation 'com.google.guava:guava:26.0-jre' // implementation is a configuration defined by the java plugin compile group: 'mysql' , name: 'mysql-connector-java' , version: '5.1.13' testImplementation 'junit:junit:4.12' } // pointer to the Java entrypoint mainClassName = \"com.someorg.someprj.App\"","title":"Gradle Basics"},{"location":"Java/Gradle/#gradle","text":"","title":"Gradle"},{"location":"Java/Gradle/#install","text":"In Windows 10 WSL, install sdkman sudo apt install zip curl -s \"https://get.sdkman.io\" | bash source \" $HOME /.sdkman/bin/sdkman-init.sh\" sdk version Install gradle sdk install gradle gradle -v Create a gradle project (for Java) cd /mnt/d/code/gradle gradle init --type java-application You can now use ./gradlew or gradlew.bat in the project folder","title":"Install"},{"location":"Java/Gradle/#usage-with-java","text":"Example for the JVM","title":"Usage with Java"},{"location":"Java/Gradle/#common-commands","text":"./gradlew tasks in your project directory lists which tasks you can run in your project, such as building or running your code. ./gradlew projects ./gradlew properties Most commonly used Java tasks: ./gradlew build will compile your project's code into a /build folder. ./gradlew run will run the compiled code in your build folder. ./gradlew clean will purge that build folder. ./gradlew test will execute unit tests without building or running your code again.","title":"Common commands"},{"location":"Java/Gradle/#build-process","text":"Gradle launches as a new JVM process It parses the gradle.properties file and configures Gradle accordingly Next, it creates a Settings instance for the build Then, it evaluates the settings.gradle file against the Settings object It creates a hierarchy of Projects, based on the configured Settings object Finally, it executes each build.gradle file against its project In case of a multi-project build, we'd probably have multiple different build.gradle files, one for each project. The build.gradle file is executed against a Project instance, with one Project instance created per subproject.","title":"Build process"},{"location":"Java/Gradle/#groovy-dsl","text":"Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application. Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.","title":"Groovy DSL"},{"location":"Java/Gradle/#tasks","text":"Tasks are snippets that we can run directly from the command line in our project directory via ./gradlew [TASK_NAME] ./gradlew copy task copy ( type: Copy , group: \"Custom\" , description: \"Copies sources to the dest directory\" ) { from \"src\" into \"dest\" } // accessing task properties println copy . destinationDir println project . copy . destinationDir task ( 'copy2' , type: Copy ) { description 'Copies the resource directory to the target directory.' from ( file ( 'src' )) into ( buildDir ) include ( '**/*.txt' , '**/*.xml' , '**/*.properties' ) timeout = Duration . ofMillis ( 50000 ) } task hello { group = 'Worthless tasks' description = 'An utterly useless task' // extra (custom) properties ext . myProperty = \"myValue\" doLast { println 'Hello world!' } } // API call hello . doLast { println \"Greetings from the $hello.name task.\" // accessing task property in interpolated string } hello . configure { doLast { println 'Hello again' } } task next { dependsOn hello // or 'hello' if lazy initialized - task dependency doLast { println hello . myProperty } } ./gradlew -q hello ./gradlew -q next // dynamic tasks 4 . times { counter -> task \"task$counter\" { doLast { println \"I'm task number $counter\" } } } // default tasks defaultTasks 'task0' , 'task1' import org.apache.commons.codec.binary.Base64 // dependencies for the build script buildscript { repositories { mavenCentral () } dependencies { classpath group: 'commons-codec' , name: 'commons-codec' , version: '1.2' } } task encode { doLast { // using the build script dependencies def byte [] encodedString = new Base64 (). encode ( 'hello world\\n' . getBytes ()) println new String ( encodedString ) } } // you can also declare methods File [] fileList ( String dir ) { file ( dir ). listFiles ({ file -> file . isFile () } as FileFilter ). sort () }","title":"Tasks"},{"location":"Java/Gradle/#plugins","text":"https://plugins.gradle.org/ plugins { id \"base\" } Essential plugins for Java: plugins { id 'java' id 'application' } apply plugin: 'application'","title":"Plugins"},{"location":"Java/Gradle/#dependencies-and-repositories","text":"repositories { jcenter () // or mavenCentral() } dependencies { implementation 'com.google.guava:guava:26.0-jre' // implementation is a configuration defined by the java plugin compile group: 'mysql' , name: 'mysql-connector-java' , version: '5.1.13' testImplementation 'junit:junit:4.12' } // pointer to the Java entrypoint mainClassName = \"com.someorg.someprj.App\"","title":"Dependencies and repositories"},{"location":"Java/Java/","text":"Install Java \u00b6 JDK download java -version Java Tools \u00b6 List 1 List 2 Eclipse IDE Maven or Graddle build tool Nexus private repository Maven public repository Phabrikator code review Phabrikator blog Jenkins CI / CD automation server JProfiler FindBugs static analysis or Checker Framework Checkstyle coding standard checker Style guidelines Java Libraries \u00b6 Libraries Log4j Spring Spring Cloud for Amazon Web Services Spring boot code generator Apache Commons Guava Jackson JSON or GSON Hibernate on the JVM. Play framework Spark web microframework Akka - actor model, to build highly concurrent, distributed, and resilient message-driven applications","title":"Java Pointers"},{"location":"Java/Java/#install-java","text":"JDK download java -version","title":"Install Java"},{"location":"Java/Java/#java-tools","text":"List 1 List 2 Eclipse IDE Maven or Graddle build tool Nexus private repository Maven public repository Phabrikator code review Phabrikator blog Jenkins CI / CD automation server JProfiler FindBugs static analysis or Checker Framework Checkstyle coding standard checker Style guidelines","title":"Java Tools"},{"location":"Java/Java/#java-libraries","text":"Libraries Log4j Spring Spring Cloud for Amazon Web Services Spring boot code generator Apache Commons Guava Jackson JSON or GSON Hibernate on the JVM. Play framework Spark web microframework Akka - actor model, to build highly concurrent, distributed, and resilient message-driven applications","title":"Java Libraries"},{"location":"Java/Log4j/","text":"Apache Log4j 2 \u00b6 Log4j quick guide Key Components \u00b6 loggers: Responsible for capturing logging information. appenders: Responsible for publishing logging information to various preferred destinations. layouts: Responsible for formatting logging information in different styles. There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERROR, WARN, FATAL, and ALL. Install \u00b6 Download Log4j $ gunzip apache-log4j-1.2.15.tar.gz $ tar -xvf apache-log4j-1.2.15.tar $ pwd /usr/local/apache-log4j-1.2.15 $ export CLASSPATH = $CLASSPATH :/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar $ export PATH = $PATH :/usr/local/apache-log4j-1.2.15/ Maven Snippet \u00b6 org.apache.logging.log4j log4j-api 2.6.1 org.apache.logging.log4j log4j-core 2.6.1 log4j.properties \u00b6 All the libraries should be available in CLASSPATH and yourlog4j.properties file should be available in PATH. # Define the root logger with appender file log = /usr/home/log4j log4j.rootLogger = WARN, FILE # Define the file appender log4j.appender.FILE = org.apache.log4j.FileAppender log4j.appender.FILE.File = ${log}/log.out # Define the layout for file appender log4j.appender.FILE.layout = org.apache.log4j.PatternLayout log4j.appender.FILE.layout.conversionPattern = %m%n Snippets \u00b6 import org.apache.logging.log4j.LogManager ; import org.apache.logging.log4j.Logger ; public class MyTest { private static final Logger logger = LogManager . getLogger (); // equiv to LogManager.getLogger(MyTest.class); private static final Logger logger = LogManager . getLogger ( \"HelloWorld\" ); public static void main ( String [] args ) { logger . setLevel ( Level . WARN ); logger . info ( \"Hello, World!\" ); // string interpolation logger . debug ( \"Logging in user {} with birthday {}\" , user . getName (), user . getBirthdayCalendar ()); // pre-Java 8 style optimization: explicitly check the log level // to make sure the expensiveOperation() method is only called if necessary if ( logger . isTraceEnabled ()) { logger . trace ( \"Some long-running operation returned {}\" , expensiveOperation ()); } // Java-8 style optimization: no need to explicitly check the log level: // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace(\"Some long-running operation returned {}\", () -> expensiveOperation()); } } // FORMATTER LOGGER public static Logger logger = LogManager . getFormatterLogger ( \"Foo\" ); logger . debug ( \"Logging in user %s with birthday %s\" , user . getName (), user . getBirthdayCalendar ()); logger . debug ( \"Logging in user %1$s with birthday %2$tm %2$te,%2$tY\" , user . getName (), user . getBirthdayCalendar ()); // logger . debug ( \"Logging in user {} with birthday {}\" , user . getName (), user . getBirthdayCalendar ());","title":"Apache Log4j 2"},{"location":"Java/Log4j/#apache-log4j-2","text":"Log4j quick guide","title":"Apache Log4j 2"},{"location":"Java/Log4j/#key-components","text":"loggers: Responsible for capturing logging information. appenders: Responsible for publishing logging information to various preferred destinations. layouts: Responsible for formatting logging information in different styles. There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERROR, WARN, FATAL, and ALL.","title":"Key Components"},{"location":"Java/Log4j/#install","text":"Download Log4j $ gunzip apache-log4j-1.2.15.tar.gz $ tar -xvf apache-log4j-1.2.15.tar $ pwd /usr/local/apache-log4j-1.2.15 $ export CLASSPATH = $CLASSPATH :/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar $ export PATH = $PATH :/usr/local/apache-log4j-1.2.15/","title":"Install"},{"location":"Java/Log4j/#maven-snippet","text":" org.apache.logging.log4j log4j-api 2.6.1 org.apache.logging.log4j log4j-core 2.6.1 ","title":"Maven Snippet"},{"location":"Java/Log4j/#log4jproperties","text":"All the libraries should be available in CLASSPATH and yourlog4j.properties file should be available in PATH. # Define the root logger with appender file log = /usr/home/log4j log4j.rootLogger = WARN, FILE # Define the file appender log4j.appender.FILE = org.apache.log4j.FileAppender log4j.appender.FILE.File = ${log}/log.out # Define the layout for file appender log4j.appender.FILE.layout = org.apache.log4j.PatternLayout log4j.appender.FILE.layout.conversionPattern = %m%n","title":"log4j.properties"},{"location":"Java/Log4j/#snippets","text":"import org.apache.logging.log4j.LogManager ; import org.apache.logging.log4j.Logger ; public class MyTest { private static final Logger logger = LogManager . getLogger (); // equiv to LogManager.getLogger(MyTest.class); private static final Logger logger = LogManager . getLogger ( \"HelloWorld\" ); public static void main ( String [] args ) { logger . setLevel ( Level . WARN ); logger . info ( \"Hello, World!\" ); // string interpolation logger . debug ( \"Logging in user {} with birthday {}\" , user . getName (), user . getBirthdayCalendar ()); // pre-Java 8 style optimization: explicitly check the log level // to make sure the expensiveOperation() method is only called if necessary if ( logger . isTraceEnabled ()) { logger . trace ( \"Some long-running operation returned {}\" , expensiveOperation ()); } // Java-8 style optimization: no need to explicitly check the log level: // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace(\"Some long-running operation returned {}\", () -> expensiveOperation()); } } // FORMATTER LOGGER public static Logger logger = LogManager . getFormatterLogger ( \"Foo\" ); logger . debug ( \"Logging in user %s with birthday %s\" , user . getName (), user . getBirthdayCalendar ()); logger . debug ( \"Logging in user %1$s with birthday %2$tm %2$te,%2$tY\" , user . getName (), user . getBirthdayCalendar ()); // logger . debug ( \"Logging in user {} with birthday {}\" , user . getName (), user . getBirthdayCalendar ());","title":"Snippets"},{"location":"Java/Maven/","text":"Useful Links \u00b6 http://maven.apache.org/ Maven Cheatsheet Maven Quick Ref Apache-maven-2 Maven Basics Maven Download / Install Nexus Basics \u00b6 Install: cd /usr/local ln -s apache-maven-3.0.5 maven export PATH = /usr/local/maven/bin: $PATH mvn -v Settings file: ~/.m2/settings.xml It contains user-specific configuration for authentication, repositories, and other information to customize the behavior of Maven. Maven Repo: ~/.m2/repository/ This directory contains your local Maven repository. When you download a dependency from a remote Maven repository, Maven stores a copy of the dependency in your local repository. Directory Layout \u00b6 Introduction to the standard directory layout Without customization, source code is assumed to be in ${basedir}/src/main/java and resources are assumed to be in ${basedir}/src/main/resources . Tests are assumed to be in ${basedir}/src/test , and a project is assumed to produce a JAR file. Maven assumes that you want the compile bytecode to ${basedir}/target/classes and then create a distributable JAR file in ${basedir}/target For WAR files , the /WEB-INF directory contains a file named web.xml which defines the structure of the web application. See also Tomcat Deployment guide Cheatsheet \u00b6 Bring up a menu of choices mvn archetype:generate -DgroupId = com.dw -DartifactId = es-demo -DarchetypeArtifactId = maven-archetype-quickstart -DinteractiveMode = false Create a Java project mvn archetype:create -DgroupId = org.yourcompany.project -DartifactId = application Create a web project mvn archetype:create -DgroupId = org.yourcompany.project -DartifactId = application -DarchetypeArtifactId = maven-archetype-webapp Clean project (will delete target directory) mvn clean Validate project (validate the project is correct and all necessary information is available) mvn validate Compile project (compile source code, classes stored in target/classes) mvn compile Test project (run tests using a suitable unit testing framework) mvn test Package project (take the compiled code and package it in its distributable format, such as a JAR / WAR) mvn package Verify project (run any checks to verify the package is valid and meets quality criteria) mvn verify Install project (install the package into the local repository, for use as a dependency in other projects locally) mvn install mvn clean install -DskipTests -Dmaven.javadoc.skip = true Deploy project (done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects) mvn deploy Deploy-file (can be used for deploying a external jar file to repository) mvn deploy:deploy-file -Dfile = /path/to/jar/file -DrepositoryId = repos-server -Durl = http ://repos.company.o You can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code. POM files \u00b6 Use the search engine at repository.sonatype.org to find dependencies by name and get the xml necessary to paste into your pom.xml 4.0.0 org.sonatype.mavenbook my-project 1.0-SNAPSHOT ","title":"Maven"},{"location":"Java/Maven/#useful-links","text":"http://maven.apache.org/ Maven Cheatsheet Maven Quick Ref Apache-maven-2 Maven Basics Maven Download / Install Nexus","title":"Useful Links"},{"location":"Java/Maven/#basics","text":"Install: cd /usr/local ln -s apache-maven-3.0.5 maven export PATH = /usr/local/maven/bin: $PATH mvn -v Settings file: ~/.m2/settings.xml It contains user-specific configuration for authentication, repositories, and other information to customize the behavior of Maven. Maven Repo: ~/.m2/repository/ This directory contains your local Maven repository. When you download a dependency from a remote Maven repository, Maven stores a copy of the dependency in your local repository.","title":"Basics"},{"location":"Java/Maven/#directory-layout","text":"Introduction to the standard directory layout Without customization, source code is assumed to be in ${basedir}/src/main/java and resources are assumed to be in ${basedir}/src/main/resources . Tests are assumed to be in ${basedir}/src/test , and a project is assumed to produce a JAR file. Maven assumes that you want the compile bytecode to ${basedir}/target/classes and then create a distributable JAR file in ${basedir}/target For WAR files , the /WEB-INF directory contains a file named web.xml which defines the structure of the web application. See also Tomcat Deployment guide","title":"Directory Layout"},{"location":"Java/Maven/#cheatsheet","text":"Bring up a menu of choices mvn archetype:generate -DgroupId = com.dw -DartifactId = es-demo -DarchetypeArtifactId = maven-archetype-quickstart -DinteractiveMode = false Create a Java project mvn archetype:create -DgroupId = org.yourcompany.project -DartifactId = application Create a web project mvn archetype:create -DgroupId = org.yourcompany.project -DartifactId = application -DarchetypeArtifactId = maven-archetype-webapp Clean project (will delete target directory) mvn clean Validate project (validate the project is correct and all necessary information is available) mvn validate Compile project (compile source code, classes stored in target/classes) mvn compile Test project (run tests using a suitable unit testing framework) mvn test Package project (take the compiled code and package it in its distributable format, such as a JAR / WAR) mvn package Verify project (run any checks to verify the package is valid and meets quality criteria) mvn verify Install project (install the package into the local repository, for use as a dependency in other projects locally) mvn install mvn clean install -DskipTests -Dmaven.javadoc.skip = true Deploy project (done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects) mvn deploy Deploy-file (can be used for deploying a external jar file to repository) mvn deploy:deploy-file -Dfile = /path/to/jar/file -DrepositoryId = repos-server -Durl = http ://repos.company.o You can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code.","title":"Cheatsheet"},{"location":"Java/Maven/#pom-files","text":"Use the search engine at repository.sonatype.org to find dependencies by name and get the xml necessary to paste into your pom.xml 4.0.0 org.sonatype.mavenbook my-project 1.0-SNAPSHOT ","title":"POM files"},{"location":"Java/Spring/","text":"Spring \u00b6 All Spring beans are managed - they \"live\" inside a container, called \"application context\". Second, each application has an entry point to that context. Web applications have a Servlet, JSFuses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener. Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context. What is \"living\" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there. Spring and AWS \u00b6 A New Way of Using Email for Support Apps: An AWS Tutorial","title":"Spring"},{"location":"Java/Spring/#spring","text":"All Spring beans are managed - they \"live\" inside a container, called \"application context\". Second, each application has an entry point to that context. Web applications have a Servlet, JSFuses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener. Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context. What is \"living\" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there.","title":"Spring"},{"location":"Java/Spring/#spring-and-aws","text":"A New Way of Using Email for Support Apps: An AWS Tutorial","title":"Spring and AWS"},{"location":"Linux/Linux/","text":"Vim \u00b6 Vim Commands Cheat Sheet :q :q! :wq :wq {file} :e[dit] {file} i insert dd delete [count] lines Bash \u00b6 BASH Programming - Introduction Bash CheatSheet for UNIX Systems Bash Cheat Sheet #!/bin/bash varname = value echo $varname Don't forget chmod +x filename Amazon Linux \u00b6 Amazon Linux Basics Adding Packages \u00b6 sudo yum update -y # all packages sudo yum install -y package_name sudo yum install -y httpd24 php56 mysql55-server php56-mysqlnd Start a Service \u00b6 sudo service docker start sudo service jenkins start sudo service nginx start Autostarting a service on Amazon Linux \u00b6 Tutorial on \"Chkconfig\" Command in Linux with Examples man page # check a service is configured for startup sudo chkconfig sshd echo $? # 0 = configured for startup # or sudo chkconfig --list mysqld sudo chkconfig --list # all services # add a service sudo chkconfig --add vsftpd sudo chkconfig mysqld on sudo chkconfig --level 3 httpd on # specific runlevel Linux Boot Process \u00b6 Linux Boot Process Scripts in /etc/init.d You can also use a /etc/rc.d/rc.local script. Running Commands on your Linux Instance at Launch \u00b6 Paste a user data script into the User data field #!/bin/bash yum update -y yum install -y httpd24 php56 mysql55-server php56-mysqlnd service httpd start chkconfig httpd on groupadd www usermod -a -G www ec2-user chown -R root:www /var/www chmod 2775 /var/www find /var/www -type d -exec chmod 2775 {} + find /var/www -type f -exec chmod 0664 {} + echo \"\" > /var/www/html/phpinfo.php Or use cloud-init cloud-init for AWS EC2 cloud-init docs File location: /etc/sysconfig/cloudinit Cloud-init output log file: /var/log/cloud-init-output.log Install the SSM Agent on EC2 Instances at Start-Up \u00b6 #!/bin/bash cd /tmp curl https://amazon-ssm-region.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm yum install -y amazon-ssm-agent.rpm Linux desktop \u00b6 How can I connect to an Amazon EC2 Linux instance with desktop functionality from Windows?","title":"Linux Cheatsheet"},{"location":"Linux/Linux/#vim","text":"Vim Commands Cheat Sheet :q :q! :wq :wq {file} :e[dit] {file} i insert dd delete [count] lines","title":"Vim"},{"location":"Linux/Linux/#bash","text":"BASH Programming - Introduction Bash CheatSheet for UNIX Systems Bash Cheat Sheet #!/bin/bash varname = value echo $varname Don't forget chmod +x filename","title":"Bash"},{"location":"Linux/Linux/#amazon-linux","text":"Amazon Linux Basics","title":"Amazon Linux"},{"location":"Linux/Linux/#adding-packages","text":"sudo yum update -y # all packages sudo yum install -y package_name sudo yum install -y httpd24 php56 mysql55-server php56-mysqlnd","title":"Adding Packages"},{"location":"Linux/Linux/#start-a-service","text":"sudo service docker start sudo service jenkins start sudo service nginx start","title":"Start a Service"},{"location":"Linux/Linux/#autostarting-a-service-on-amazon-linux","text":"Tutorial on \"Chkconfig\" Command in Linux with Examples man page # check a service is configured for startup sudo chkconfig sshd echo $? # 0 = configured for startup # or sudo chkconfig --list mysqld sudo chkconfig --list # all services # add a service sudo chkconfig --add vsftpd sudo chkconfig mysqld on sudo chkconfig --level 3 httpd on # specific runlevel","title":"Autostarting a service on Amazon Linux"},{"location":"Linux/Linux/#linux-boot-process","text":"Linux Boot Process Scripts in /etc/init.d You can also use a /etc/rc.d/rc.local script.","title":"Linux Boot Process"},{"location":"Linux/Linux/#running-commands-on-your-linux-instance-at-launch","text":"Paste a user data script into the User data field #!/bin/bash yum update -y yum install -y httpd24 php56 mysql55-server php56-mysqlnd service httpd start chkconfig httpd on groupadd www usermod -a -G www ec2-user chown -R root:www /var/www chmod 2775 /var/www find /var/www -type d -exec chmod 2775 {} + find /var/www -type f -exec chmod 0664 {} + echo \"\" > /var/www/html/phpinfo.php Or use cloud-init cloud-init for AWS EC2 cloud-init docs File location: /etc/sysconfig/cloudinit Cloud-init output log file: /var/log/cloud-init-output.log","title":"Running Commands on your Linux Instance at Launch"},{"location":"Linux/Linux/#install-the-ssm-agent-on-ec2-instances-at-start-up","text":"#!/bin/bash cd /tmp curl https://amazon-ssm-region.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm yum install -y amazon-ssm-agent.rpm","title":"Install the SSM Agent on EC2 Instances at Start-Up"},{"location":"Linux/Linux/#linux-desktop","text":"How can I connect to an Amazon EC2 Linux instance with desktop functionality from Windows?","title":"Linux desktop"},{"location":"Linux/Virtualization/","text":"Virtualization \u00b6 Comparison of platform virtual machines Linux KVM Xen VMware ESX vSphere","title":"Virtualization"},{"location":"Linux/Virtualization/#virtualization","text":"Comparison of platform virtual machines Linux KVM Xen VMware ESX vSphere","title":"Virtualization"},{"location":"Markup_and_Documentation/Jekyll/","text":"Jekyll Basics \u00b6 Jekyll Home Page Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll\u2019s GitHub repo . If you have questions, you can ask them on Jekyll Talk . Jekyll source code Guide to basic Jekyll Jekyll Install How-To \u00b6 Install Instructions Install Ruby via RubyInstaller Update RubyGems $ gem update --system Install Jekyll $ gem install jekyll Test Jekyll $ jekyll --version $ gem list jekyll Install bundler $ gem install bundler Bundler is a gem that manages other Ruby gems. It makes sure your gems and gem versions are compatible, and that you have all necessary dependencies each gem requires. Create a new site # Create a new Jekyll site at ./myblog ~ $ jekyll new myblog # Change into your new directory ~ $ cd myblog Jekyll installs a site that uses a gem-based theme called Minima. With gem-based themes, some of the site\u2019s directories (such as the assets, _layouts, _includes, and _sass directories) are stored in the theme\u2019s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll\u2019s build process. Build site locally # Build the site on the preview server ~/myblog $ bundle exec jekyll serve Now browse to localhost:4000 Jekyll Quickstart When you run bundle exec jekyll serve, Bundler uses the gems and versions as specified in Gemfile.lock to ensure your Jekyll site builds with no compatibility or dependency conflicts. The Gemfile and Gemfile.lock files inform Bundler about the gem requirements in your site. If your site doesn\u2019t have these Gemfiles, you can omit bundle exec and just run jekyll serve. $ jekyll build # => The current folder will be generated into ./_site $ jekyll serve # => A development server will run at http://localhost:4000/ # Auto-regeneration: enabled. Use `--no-watch` to disable. Plugins \u00b6 $ gem install jekyll-sitemap $ gem install jekyll-feed etc... Add to _config.yml gems: - jekyll-paginate - jekyll-feed - jekyll-sitemap `` # Custom Search [Adding a custom Google search](http://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/) # Themes [Theme documentation](https://jekyllrb.com/docs/themes/) To change theme, search for jekyll theme on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes. Add the theme to your site\u2019s Gemfile: gem \"jekyll-theme-tactile\" ```bash $ bundle install # check proper install $ bundle show jekyll-theme-tactile Add the following to your site\u2019s _config.yml to activate the theme: theme: jekyll-theme-tactile Build your site: $ bundle exec jekyll serve You can find out info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at jekyllrb.com You can find the source code for the Jekyll minima theme at: minima You\u2019ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve , which launches a web server and auto-regenerates your site when a file is updated. To add new posts, simply add a file in the _posts directory that follows the convention YYYY-MM-DD-name-of-post.ext and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: {% highlight ruby %} def print_hi(name) puts \"Hi, #{name}\" end print_hi('Tom') => prints 'Hi, Tom' to STDOUT. \u00b6 {% endhighlight %}","title":"Jekyll How-To"},{"location":"Markup_and_Documentation/Jekyll/#jekyll-basics","text":"Jekyll Home Page Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll\u2019s GitHub repo . If you have questions, you can ask them on Jekyll Talk . Jekyll source code Guide to basic Jekyll","title":"Jekyll Basics"},{"location":"Markup_and_Documentation/Jekyll/#jekyll-install-how-to","text":"Install Instructions Install Ruby via RubyInstaller Update RubyGems $ gem update --system Install Jekyll $ gem install jekyll Test Jekyll $ jekyll --version $ gem list jekyll Install bundler $ gem install bundler Bundler is a gem that manages other Ruby gems. It makes sure your gems and gem versions are compatible, and that you have all necessary dependencies each gem requires. Create a new site # Create a new Jekyll site at ./myblog ~ $ jekyll new myblog # Change into your new directory ~ $ cd myblog Jekyll installs a site that uses a gem-based theme called Minima. With gem-based themes, some of the site\u2019s directories (such as the assets, _layouts, _includes, and _sass directories) are stored in the theme\u2019s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll\u2019s build process. Build site locally # Build the site on the preview server ~/myblog $ bundle exec jekyll serve Now browse to localhost:4000 Jekyll Quickstart When you run bundle exec jekyll serve, Bundler uses the gems and versions as specified in Gemfile.lock to ensure your Jekyll site builds with no compatibility or dependency conflicts. The Gemfile and Gemfile.lock files inform Bundler about the gem requirements in your site. If your site doesn\u2019t have these Gemfiles, you can omit bundle exec and just run jekyll serve. $ jekyll build # => The current folder will be generated into ./_site $ jekyll serve # => A development server will run at http://localhost:4000/ # Auto-regeneration: enabled. Use `--no-watch` to disable.","title":"Jekyll Install How-To"},{"location":"Markup_and_Documentation/Jekyll/#plugins","text":"$ gem install jekyll-sitemap $ gem install jekyll-feed etc... Add to _config.yml gems: - jekyll-paginate - jekyll-feed - jekyll-sitemap `` # Custom Search [Adding a custom Google search](http://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/) # Themes [Theme documentation](https://jekyllrb.com/docs/themes/) To change theme, search for jekyll theme on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes. Add the theme to your site\u2019s Gemfile: gem \"jekyll-theme-tactile\" ```bash $ bundle install # check proper install $ bundle show jekyll-theme-tactile Add the following to your site\u2019s _config.yml to activate the theme: theme: jekyll-theme-tactile Build your site: $ bundle exec jekyll serve You can find out info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at jekyllrb.com You can find the source code for the Jekyll minima theme at: minima You\u2019ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve , which launches a web server and auto-regenerates your site when a file is updated. To add new posts, simply add a file in the _posts directory that follows the convention YYYY-MM-DD-name-of-post.ext and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: {% highlight ruby %} def print_hi(name) puts \"Hi, #{name}\" end print_hi('Tom')","title":"Plugins"},{"location":"Markup_and_Documentation/Jekyll/#-prints-hi-tom-to-stdout","text":"{% endhighlight %}","title":"=> prints 'Hi, Tom' to STDOUT."},{"location":"Markup_and_Documentation/Markdown/","text":"Markdown Essentials \u00b6 Markdown main site GitHub Flavored Markdown Guide Basics \u00b6 A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs. Do not indent normal paragraphs with spaces or tabs. Indent at least 4 spaces or a tab for code blocks. Syntax highlighted code block # Header 1 ## Header 2 ### Header 3 - Bulleted - List 1. Numbered 2. List **Bold** and _Italic_ and `Code` text [Link](url) and ![Image](src) Emphasis \u00b6 *single asterisks* _single underscores_ **double asterisks** __double underscores__ Emphasis can be used in the mi\\*dd\\*le of a word. Headers \u00b6 # H1 ## H2 ### H3 #### H4 ##### H5 ###### H6 Alt-H1 ====== Alt-H2 ------ Links and Images \u00b6 [ Text for the link ](URL) This is [an example][id] reference-style link. [id]: http://example.com/ \"Optional Title Here\" ![Alt text](/path/to/img.jpg \"Optional title\") Code \u00b6 `span of code` ```python def wiki_rocks(text): formatter = lambda t: \"funky\"+t return formatter(text) ``` will be displayed as def wiki_rocks ( text ): formatter = lambda t : \"funky\" + t return formatter ( text ) Blockquotes \u00b6 > This is a blockquote with two paragraphs. > > Second paragraph. GitHub Pages \u00b6 GitHub Pages documentation GitHub Pages site will use the layout and styles from the Jekyll theme you have selected in your repository settings . The name of this theme is saved in the Jekyll _config.yml configuration file. Bitbucket \u00b6 Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. Safe mode requires that you replace, remove, or escape HTML tags appropriately. Code highlighting to bitbucket README.md written in Python Markdown friends = [ 'john' , 'pat' , 'gary' , 'michael' ] for i , name in enumerate ( friends ): print \"iteration {iteration} is {name} \" . format ( iteration = i , name = name ) Python markdown main site Cloning your Bitbucket Wiki \u00b6 $ git clone http://bitbucket.org/MY_USER/MY_REPO/wiki","title":"Markdown Essentials"},{"location":"Markup_and_Documentation/Markdown/#markdown-essentials","text":"Markdown main site GitHub Flavored Markdown Guide","title":"Markdown Essentials"},{"location":"Markup_and_Documentation/Markdown/#basics","text":"A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs. Do not indent normal paragraphs with spaces or tabs. Indent at least 4 spaces or a tab for code blocks. Syntax highlighted code block # Header 1 ## Header 2 ### Header 3 - Bulleted - List 1. Numbered 2. List **Bold** and _Italic_ and `Code` text [Link](url) and ![Image](src)","title":"Basics"},{"location":"Markup_and_Documentation/Markdown/#emphasis","text":"*single asterisks* _single underscores_ **double asterisks** __double underscores__ Emphasis can be used in the mi\\*dd\\*le of a word.","title":"Emphasis"},{"location":"Markup_and_Documentation/Markdown/#headers","text":"# H1 ## H2 ### H3 #### H4 ##### H5 ###### H6 Alt-H1 ====== Alt-H2 ------","title":"Headers"},{"location":"Markup_and_Documentation/Markdown/#links-and-images","text":"[ Text for the link ](URL) This is [an example][id] reference-style link. [id]: http://example.com/ \"Optional Title Here\" ![Alt text](/path/to/img.jpg \"Optional title\")","title":"Links and Images"},{"location":"Markup_and_Documentation/Markdown/#code","text":"`span of code` ```python def wiki_rocks(text): formatter = lambda t: \"funky\"+t return formatter(text) ``` will be displayed as def wiki_rocks ( text ): formatter = lambda t : \"funky\" + t return formatter ( text )","title":"Code"},{"location":"Markup_and_Documentation/Markdown/#blockquotes","text":"> This is a blockquote with two paragraphs. > > Second paragraph.","title":"Blockquotes"},{"location":"Markup_and_Documentation/Markdown/#github-pages","text":"GitHub Pages documentation GitHub Pages site will use the layout and styles from the Jekyll theme you have selected in your repository settings . The name of this theme is saved in the Jekyll _config.yml configuration file.","title":"GitHub Pages"},{"location":"Markup_and_Documentation/Markdown/#bitbucket","text":"Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. Safe mode requires that you replace, remove, or escape HTML tags appropriately. Code highlighting to bitbucket README.md written in Python Markdown friends = [ 'john' , 'pat' , 'gary' , 'michael' ] for i , name in enumerate ( friends ): print \"iteration {iteration} is {name} \" . format ( iteration = i , name = name ) Python markdown main site","title":"Bitbucket"},{"location":"Markup_and_Documentation/Markdown/#cloning-your-bitbucket-wiki","text":"$ git clone http://bitbucket.org/MY_USER/MY_REPO/wiki","title":"Cloning your Bitbucket Wiki"},{"location":"Markup_and_Documentation/MkDocs/","text":"This website is generated by mkdocs.org and the Material Theme . Basic MkDocs Commands \u00b6 mkdocs new [dir-name] - Create a new project. mkdocs serve - Start the live-reloading docs server. mkdocs build - Build the documentation site. mkdocs help - Print this help message. Install and documentation generation \u00b6 mkdocs.org . To install MkDocs / create a new documentation site: $ pip install mkdocs $ mkdocs new documentation To build the documentation site: $ cd documentation $ mkdocs build To start the live-reloading docs server - http://localhost:8000/ $ mkdocs serve MkDocs can use the ghp-import tool to commit to the gh-pages branch and push the gh-pages branch to GitHub Pages: $ mkdocs gh-deploy MkDocs project layout \u00b6 mkdocs.yml # The configuration file. docs/ index.md # The documentation homepage. ... # Other markdown pages, images and other files.","title":"MkDocs Basics"},{"location":"Markup_and_Documentation/MkDocs/#basic-mkdocs-commands","text":"mkdocs new [dir-name] - Create a new project. mkdocs serve - Start the live-reloading docs server. mkdocs build - Build the documentation site. mkdocs help - Print this help message.","title":"Basic MkDocs Commands"},{"location":"Markup_and_Documentation/MkDocs/#install-and-documentation-generation","text":"mkdocs.org . To install MkDocs / create a new documentation site: $ pip install mkdocs $ mkdocs new documentation To build the documentation site: $ cd documentation $ mkdocs build To start the live-reloading docs server - http://localhost:8000/ $ mkdocs serve MkDocs can use the ghp-import tool to commit to the gh-pages branch and push the gh-pages branch to GitHub Pages: $ mkdocs gh-deploy","title":"Install and documentation generation"},{"location":"Markup_and_Documentation/MkDocs/#mkdocs-project-layout","text":"mkdocs.yml # The configuration file. docs/ index.md # The documentation homepage. ... # Other markdown pages, images and other files.","title":"MkDocs project layout"},{"location":"Markup_and_Documentation/reStructuredText/","text":"reStructuredText \u00b6 reStructuredText Quick Ref reStructuredText Cheat Sheet (see below) reST Short Overview \u00b6 All reST files use an indentation of 3 spaces; no tabs are allowed. The maximum line length is 80 characters for normal text, but tables, deeply indented code samples and long links may extend beyond that. Code example bodies should use normal Python 4-space indentation. Paragraphs are simply chunks of text separated by one or more blank lines. As in Python, indentation is significant in reST, so all lines of the same paragraph must be left-aligned to the same level of indentation. Section headers are created by underlining (and optionally overlining) the section title with a punctuation character, at least as long as the text: ================= This is a heading ================= # with overline, for parts * with overline, for chapters = for sections - for subsections ^ for subsubsections \" for paragraphs one asterisk: *text* for emphasis (italics), two asterisks: **text** for strong emphasis (boldface), and backquotes: ``text`` for code samples. escape with a backslash \\ * This is a bulleted list. * It has two items, the second item uses two lines. 1. This is a numbered list. 2. It has two items too. . This is a numbered list. . It has two items too. Nested lists are possible, but be aware that they must be separated from the parent list items by blank lines Source Code Double Colon \u00b6 This is a normal text paragraph. The next paragraph is a code sample:: It is not processed in any way, except that the indentation is removed. It can span multiple lines. This is a normal text paragraph again. Links \u00b6 `Link text `_ for inline web links. Definitions \u00b6 term (up to a line of text) Definition of the term, which must be indented and can even consist of multiple paragraphs next term Description. Footnotes \u00b6 Lorem ipsum [#]_ dolor sit amet ... [#]_ Use of reStructuredText in Python docstrings \u00b6 See http://infinitemonkeycorps.net/docs/pph/ # Typical function documentation: :param volume_id: The ID of the EBS volume to be attached. :type volume_id: str :param instance_id: The ID of the EC2 instance :type instance_id: str :return: `Reverse geocoder return value`_ dictionary giving closest address(es) to `(lat, lng)` :rtype: dict :raises GoogleMapsError: If the coordinates could not be reverse geocoded. Keyword arguments and return value are identical to those of :meth:`geocode()`. .. _`Reverse geocoder return value`: http://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding Normal docstring formatting conventions apply: see PEP 257. Identifier references go in `backticks`. :param lat: some text documents parameters :type lat: float documents parameter types :return: dictionary giving some info... documents return values :rtype: dict documents return type :raises SomeError: sometext... documents exceptions raised >>> starts a doctest and is automatically formatted as code Code can also be indicated by indenting four spaces or preceding with :: and a blank line Link to other methods, functions, classes, modules with :meth: mymethod , :func: myfunc , :class: myclass , and :mod: mymodule . Hyperlink names go in backticks with a trailing underscore: Google _ Targets can be defined anywhere with: .. _Google: http://www.google.com/ Explicit Markup \u00b6 An explicit markup block begins with a line starting with .. followed by whitespace and is terminated by the next paragraph at the same level of indentation. (There needs to be a blank line between explicit markup and normal paragraphs. .. sectionauthor:: Guido van Rossum .. rubric:: Footnotes .. [#] Text of the first footnote. .. [#] Text of the second footnote. :mod:`parrot` -- Dead parrot access =================================== .. module:: parrot :platform: Unix, Windows :synopsis: Analyze and reanimate dead parrots. .. moduleauthor:: Eric Cleese .. moduleauthor:: John Idle .. function:: repeat([repeat=3[, number=1000000]]) repeat(y, z) :bar: no Return a line of text input from the user. .. class:: Spam Description of the class. .. data:: ham Description of the attribute. Inline markup \u00b6 :rolename:`content` or :role:`title ` :meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text. The following roles refer to objects in modules and are possibly hyperlinked if a matching identifier is found: mod The name of a module; a dotted name may be used. This should also be used for package names. func The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers. data The name of a module-level variable or constant. const The name of a \u201cdefined\u201d constant. This may be a C-language #define or a Python variable that is not intended to be changed. class A class name; a dotted name may be used. meth The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used. attr The name of a data attribute of an object. exc The name of an exception. A dotted name may be used. Official reStructuredText Cheatsheet \u00b6 ===================================================== The reStructuredText_ Cheat Sheet: Syntax Reminders ===================================================== :Info: See for introductory docs. :Author: David Goodger :Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $ :Revision: $Revision: 7612 $ :Description: This is a \"docinfo block\", or bibliographic field list .. NOTE:: If you are reading this as HTML, please read ``_ instead to see the input syntax examples! Section Structure ================= Section titles are underlined or overlined & underlined. Body Elements ============= Grid table: +--------------------------------+-----------------------------------+ | Paragraphs are flush-left, | Literal block, preceded by \"::\":: | | separated by blank lines. | | | | Indented | | Block quotes are indented. | | +--------------------------------+ or:: | | >>> print 'Doctest block' | | | Doctest block | > Quoted | +--------------------------------+-----------------------------------+ | | Line blocks preserve line breaks & indents. [new in 0.3.6] | | | Useful for addresses, verse, and adornment-free lists; long | | lines can be wrapped with continuation lines. | +--------------------------------------------------------------------+ Simple tables: ================ ============================================================ List Type Examples (syntax in the `text source `_) ================ ============================================================ Bullet list * items begin with \"-\", \"+\", or \"*\" Enumerated list 1. items use any variation of \"1.\", \"A)\", and \"(i)\" #. also auto-enumerated Definition list Term is flush-left : optional classifier Definition is indented, no blank line between Field list :field name: field body Option list -o at least 2 spaces between option & description ================ ============================================================ ================ ============================================================ Explicit Markup Examples (visible in the `text source`_) ================ ============================================================ Footnote .. [1] Manually numbered or [#] auto-numbered (even [#labelled]) or [*] auto-symbol Citation .. [CIT2002] A citation. Hyperlink Target .. _reStructuredText: http://docutils.sf.net/rst.html .. _indirect target: reStructuredText_ .. _internal target: Anonymous Target __ http://docutils.sf.net/docs/ref/rst/restructuredtext.html Directive (\"::\") .. image:: images/biohazard.png Substitution Def .. |substitution| replace:: like an inline directive Comment .. is anything else Empty Comment (\"..\" on a line by itself, with blank lines before & after, used to separate indentation contexts) ================ ============================================================ Inline Markup ============= *emphasis*; **strong emphasis**; `interpreted text`; `interpreted text with role`:emphasis:; ``inline literal text``; standalone hyperlink, http://docutils.sourceforge.net; named reference, reStructuredText_; `anonymous reference`__; footnote reference, [1]_; citation reference, [CIT2002]_; |substitution|; _`inline internal target`. Directive Quick Reference ========================= See for full info. ================ ============================================================ Directive Name Description (Docutils version added to, in [brackets]) ================ ============================================================ attention Specific admonition; also \"caution\", \"danger\", \"error\", \"hint\", \"important\", \"note\", \"tip\", \"warning\" admonition Generic titled admonition: ``.. admonition:: By The Way`` image ``.. image:: picture.png``; many options possible figure Like \"image\", but with optional caption and legend topic ``.. topic:: Title``; like a mini section sidebar ``.. sidebar:: Title``; like a mini parallel document parsed-literal A literal block with parsed inline markup rubric ``.. rubric:: Informal Heading`` epigraph Block quote with class=\"epigraph\" highlights Block quote with class=\"highlights\" pull-quote Block quote with class=\"pull-quote\" compound Compound paragraphs [0.3.6] container Generic block-level container element [0.3.10] table Create a titled table [0.3.1] list-table Create a table from a uniform two-level bullet list [0.3.8] csv-table Create a table from CSV data [0.3.4] contents Generate a table of contents sectnum Automatically number sections, subsections, etc. header, footer Create document decorations [0.3.8] target-notes Create an explicit footnote for each external target math Mathematical notation (input in LaTeX format) meta HTML-specific metadata include Read an external reST file as if it were inline raw Non-reST data passed untouched to the Writer replace Replacement text for substitution definitions unicode Unicode character code conversion for substitution defs date Generates today's date; for substitution defs class Set a \"class\" attribute on the next element role Create a custom interpreted text role [0.3.2] default-role Set the default interpreted text role [0.3.10] title Set the metadata document title [0.3.10] ================ ============================================================ Interpreted Text Role Quick Reference ===================================== See for full info. ================ ============================================================ Role Name Description ================ ============================================================ emphasis Equivalent to *emphasis* literal Equivalent to ``literal`` but processes backslash escapes math Mathematical notation (input in LaTeX format) PEP Reference to a numbered Python Enhancement Proposal RFC Reference to a numbered Internet Request For Comments raw For non-reST data; cannot be used directly (see docs) [0.3.6] strong Equivalent to **strong** sub Subscript sup Superscript title Title reference (book, etc.); standard default role ================ ============================================================","title":"reStructuredText Cheatsheet"},{"location":"Markup_and_Documentation/reStructuredText/#restructuredtext","text":"reStructuredText Quick Ref reStructuredText Cheat Sheet (see below)","title":"reStructuredText"},{"location":"Markup_and_Documentation/reStructuredText/#rest-short-overview","text":"All reST files use an indentation of 3 spaces; no tabs are allowed. The maximum line length is 80 characters for normal text, but tables, deeply indented code samples and long links may extend beyond that. Code example bodies should use normal Python 4-space indentation. Paragraphs are simply chunks of text separated by one or more blank lines. As in Python, indentation is significant in reST, so all lines of the same paragraph must be left-aligned to the same level of indentation. Section headers are created by underlining (and optionally overlining) the section title with a punctuation character, at least as long as the text: ================= This is a heading ================= # with overline, for parts * with overline, for chapters = for sections - for subsections ^ for subsubsections \" for paragraphs one asterisk: *text* for emphasis (italics), two asterisks: **text** for strong emphasis (boldface), and backquotes: ``text`` for code samples. escape with a backslash \\ * This is a bulleted list. * It has two items, the second item uses two lines. 1. This is a numbered list. 2. It has two items too. . This is a numbered list. . It has two items too. Nested lists are possible, but be aware that they must be separated from the parent list items by blank lines","title":"reST Short Overview"},{"location":"Markup_and_Documentation/reStructuredText/#source-code-double-colon","text":"This is a normal text paragraph. The next paragraph is a code sample:: It is not processed in any way, except that the indentation is removed. It can span multiple lines. This is a normal text paragraph again.","title":"Source Code Double Colon"},{"location":"Markup_and_Documentation/reStructuredText/#links","text":"`Link text `_ for inline web links.","title":"Links"},{"location":"Markup_and_Documentation/reStructuredText/#definitions","text":"term (up to a line of text) Definition of the term, which must be indented and can even consist of multiple paragraphs next term Description.","title":"Definitions"},{"location":"Markup_and_Documentation/reStructuredText/#footnotes","text":"Lorem ipsum [#]_ dolor sit amet ... [#]_","title":"Footnotes"},{"location":"Markup_and_Documentation/reStructuredText/#use-of-restructuredtext-in-python-docstrings","text":"See http://infinitemonkeycorps.net/docs/pph/ # Typical function documentation: :param volume_id: The ID of the EBS volume to be attached. :type volume_id: str :param instance_id: The ID of the EC2 instance :type instance_id: str :return: `Reverse geocoder return value`_ dictionary giving closest address(es) to `(lat, lng)` :rtype: dict :raises GoogleMapsError: If the coordinates could not be reverse geocoded. Keyword arguments and return value are identical to those of :meth:`geocode()`. .. _`Reverse geocoder return value`: http://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding Normal docstring formatting conventions apply: see PEP 257. Identifier references go in `backticks`. :param lat: some text documents parameters :type lat: float documents parameter types :return: dictionary giving some info... documents return values :rtype: dict documents return type :raises SomeError: sometext... documents exceptions raised >>> starts a doctest and is automatically formatted as code Code can also be indicated by indenting four spaces or preceding with :: and a blank line Link to other methods, functions, classes, modules with :meth: mymethod , :func: myfunc , :class: myclass , and :mod: mymodule . Hyperlink names go in backticks with a trailing underscore: Google _ Targets can be defined anywhere with: .. _Google: http://www.google.com/","title":"Use of reStructuredText in Python docstrings"},{"location":"Markup_and_Documentation/reStructuredText/#explicit-markup","text":"An explicit markup block begins with a line starting with .. followed by whitespace and is terminated by the next paragraph at the same level of indentation. (There needs to be a blank line between explicit markup and normal paragraphs. .. sectionauthor:: Guido van Rossum .. rubric:: Footnotes .. [#] Text of the first footnote. .. [#] Text of the second footnote. :mod:`parrot` -- Dead parrot access =================================== .. module:: parrot :platform: Unix, Windows :synopsis: Analyze and reanimate dead parrots. .. moduleauthor:: Eric Cleese .. moduleauthor:: John Idle .. function:: repeat([repeat=3[, number=1000000]]) repeat(y, z) :bar: no Return a line of text input from the user. .. class:: Spam Description of the class. .. data:: ham Description of the attribute.","title":"Explicit Markup"},{"location":"Markup_and_Documentation/reStructuredText/#inline-markup","text":":rolename:`content` or :role:`title ` :meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text. The following roles refer to objects in modules and are possibly hyperlinked if a matching identifier is found: mod The name of a module; a dotted name may be used. This should also be used for package names. func The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers. data The name of a module-level variable or constant. const The name of a \u201cdefined\u201d constant. This may be a C-language #define or a Python variable that is not intended to be changed. class A class name; a dotted name may be used. meth The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used. attr The name of a data attribute of an object. exc The name of an exception. A dotted name may be used.","title":"Inline markup"},{"location":"Markup_and_Documentation/reStructuredText/#official-restructuredtext-cheatsheet","text":"===================================================== The reStructuredText_ Cheat Sheet: Syntax Reminders ===================================================== :Info: See for introductory docs. :Author: David Goodger :Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $ :Revision: $Revision: 7612 $ :Description: This is a \"docinfo block\", or bibliographic field list .. NOTE:: If you are reading this as HTML, please read ``_ instead to see the input syntax examples! Section Structure ================= Section titles are underlined or overlined & underlined. Body Elements ============= Grid table: +--------------------------------+-----------------------------------+ | Paragraphs are flush-left, | Literal block, preceded by \"::\":: | | separated by blank lines. | | | | Indented | | Block quotes are indented. | | +--------------------------------+ or:: | | >>> print 'Doctest block' | | | Doctest block | > Quoted | +--------------------------------+-----------------------------------+ | | Line blocks preserve line breaks & indents. [new in 0.3.6] | | | Useful for addresses, verse, and adornment-free lists; long | | lines can be wrapped with continuation lines. | +--------------------------------------------------------------------+ Simple tables: ================ ============================================================ List Type Examples (syntax in the `text source `_) ================ ============================================================ Bullet list * items begin with \"-\", \"+\", or \"*\" Enumerated list 1. items use any variation of \"1.\", \"A)\", and \"(i)\" #. also auto-enumerated Definition list Term is flush-left : optional classifier Definition is indented, no blank line between Field list :field name: field body Option list -o at least 2 spaces between option & description ================ ============================================================ ================ ============================================================ Explicit Markup Examples (visible in the `text source`_) ================ ============================================================ Footnote .. [1] Manually numbered or [#] auto-numbered (even [#labelled]) or [*] auto-symbol Citation .. [CIT2002] A citation. Hyperlink Target .. _reStructuredText: http://docutils.sf.net/rst.html .. _indirect target: reStructuredText_ .. _internal target: Anonymous Target __ http://docutils.sf.net/docs/ref/rst/restructuredtext.html Directive (\"::\") .. image:: images/biohazard.png Substitution Def .. |substitution| replace:: like an inline directive Comment .. is anything else Empty Comment (\"..\" on a line by itself, with blank lines before & after, used to separate indentation contexts) ================ ============================================================ Inline Markup ============= *emphasis*; **strong emphasis**; `interpreted text`; `interpreted text with role`:emphasis:; ``inline literal text``; standalone hyperlink, http://docutils.sourceforge.net; named reference, reStructuredText_; `anonymous reference`__; footnote reference, [1]_; citation reference, [CIT2002]_; |substitution|; _`inline internal target`. Directive Quick Reference ========================= See for full info. ================ ============================================================ Directive Name Description (Docutils version added to, in [brackets]) ================ ============================================================ attention Specific admonition; also \"caution\", \"danger\", \"error\", \"hint\", \"important\", \"note\", \"tip\", \"warning\" admonition Generic titled admonition: ``.. admonition:: By The Way`` image ``.. image:: picture.png``; many options possible figure Like \"image\", but with optional caption and legend topic ``.. topic:: Title``; like a mini section sidebar ``.. sidebar:: Title``; like a mini parallel document parsed-literal A literal block with parsed inline markup rubric ``.. rubric:: Informal Heading`` epigraph Block quote with class=\"epigraph\" highlights Block quote with class=\"highlights\" pull-quote Block quote with class=\"pull-quote\" compound Compound paragraphs [0.3.6] container Generic block-level container element [0.3.10] table Create a titled table [0.3.1] list-table Create a table from a uniform two-level bullet list [0.3.8] csv-table Create a table from CSV data [0.3.4] contents Generate a table of contents sectnum Automatically number sections, subsections, etc. header, footer Create document decorations [0.3.8] target-notes Create an explicit footnote for each external target math Mathematical notation (input in LaTeX format) meta HTML-specific metadata include Read an external reST file as if it were inline raw Non-reST data passed untouched to the Writer replace Replacement text for substitution definitions unicode Unicode character code conversion for substitution defs date Generates today's date; for substitution defs class Set a \"class\" attribute on the next element role Create a custom interpreted text role [0.3.2] default-role Set the default interpreted text role [0.3.10] title Set the metadata document title [0.3.10] ================ ============================================================ Interpreted Text Role Quick Reference ===================================== See for full info. ================ ============================================================ Role Name Description ================ ============================================================ emphasis Equivalent to *emphasis* literal Equivalent to ``literal`` but processes backslash escapes math Mathematical notation (input in LaTeX format) PEP Reference to a numbered Python Enhancement Proposal RFC Reference to a numbered Internet Request For Comments raw For non-reST data; cannot be used directly (see docs) [0.3.6] strong Equivalent to **strong** sub Subscript sup Superscript title Title reference (book, etc.); standard default role ================ ============================================================","title":"Official reStructuredText Cheatsheet"},{"location":"Microservices/Microservices/","text":"MicroServices \u00b6 microservices.io Introduction to microservices Scala \u00b6 Lagom .NET \u00b6 Microservices in C#","title":"Microservices"},{"location":"Microservices/Microservices/#microservices","text":"microservices.io Introduction to microservices","title":"MicroServices"},{"location":"Microservices/Microservices/#scala","text":"Lagom","title":"Scala"},{"location":"Microservices/Microservices/#net","text":"Microservices in C#","title":".NET"},{"location":"Privacy/Privacy_engineering/","text":"Privacy Engineering \u00b6 Interesting Links \u00b6 Homomorphic Encryption","title":"Privacy Engineering"},{"location":"Privacy/Privacy_engineering/#privacy-engineering","text":"","title":"Privacy Engineering"},{"location":"Privacy/Privacy_engineering/#interesting-links","text":"Homomorphic Encryption","title":"Interesting Links"},{"location":"Python/Flask/","text":"Flask \u00b6 Useful Flask modules \u00b6 Flask-Login Flask-SSLify Flask-RESTPlus Building beautiful REST APIs using Flask, Swagger UI and Flask-RESTPlus","title":"Flask"},{"location":"Python/Flask/#flask","text":"","title":"Flask"},{"location":"Python/Flask/#useful-flask-modules","text":"Flask-Login Flask-SSLify Flask-RESTPlus Building beautiful REST APIs using Flask, Swagger UI and Flask-RESTPlus","title":"Useful Flask modules"},{"location":"Python/Jupyter/","text":"IPython / Jupyter \u00b6 Using IPython makes interactive work easy. Better shell Notebook interface Embeddable kernel Parallel python IPython shell shortcuts \u00b6 TAB expansion to complete python names and file paths ~ and * directory / file expansion many \"magic\" methods: %lsmagic # list of all magic methods %quickref # cheatsheet %magic Help \u00b6 ? # overall help help # python help system ?someobj or someobj? # help ??someobj or someobj?? # detailed help %pdoc %pdef %psource for docstring, function definition, source code only. Run \u00b6 To run a program directly from the IPython console: %run somescript.py # instead of execfile(\"somescript.py\") at the python prompt %run has special flags for timing the execution of your scripts ( -t ) or for running them under the control of either Python's pdb debugger ( -d ) or profiler ( -p ): %run -d myscript.py Other Commands \u00b6 %edit %ed # edit then execute %save %load example.py # load local (example) file (or url) allowing modification %load http://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py %macro # define macro with range of history lines, filenames or string objects %recall %whos # list identifiers you have defined interactively %reset -f -s # remove objects -f for force -s for soft (leaves history). %reset is not a kernel restart Restart with Ctrl+. in \"qtconsole\" import module ; reload(module) to reload a module from disk Debugging \u00b6 %debug # jump into the Python debugger (pdb) %pdb # start the debugger on any uncaught exception. %cd # change directory %pwd # print working directory %env # OS environment variables OS Commands \u00b6 !OScommand !ping www.bbc.co.uk %alias # system command alias History \u00b6 _ __ ___ # etc... for previous outputs. _i _ii _i4 # etc.. for previous input. _ih for list of previous inputs GUI integration \u00b6 Start with ipython --gui=qt or at the IPython prompt: %gui wx Arguments can be wx , qt , gtk and tk . Matplotlib / pylab graphics in an iPython shell \u00b6 Start with: ipython --matplotlib ( or --matplotlib=qt etc...) At the IPython prompt: %matplotlib # set matplotlib to work interactively; does not import anythig %matplotlib inline %matplotlib qt # request a specific GUI backend %pylab inline %pylab makes the following imports: import numpy import matplotlib from matplotlib import pylab , mlab , pyplot np = numpy plt = pyplot from IPython.display import display from IPython.core.pylabtools import figsize , getfigs from pylab import * from numpy import * Qtconsole - an improved console \u00b6 At the command prompt: ipython.exe qtconsole --pylab=inline --ConsoleWidget.font_size=10 alternative: --matplotlib inline or within IPython: %matplotlib inline %pylab inline To embed plots, SVG or HTML in qtconsole, call display: from IPython.core.display import display, display_html from IPython.core.display import display_png, display_svg display(plt.gcf()) # embeds the current figure in the qtconsole display(*getfigs()) # embeds all active figures in the qtconsole #or: f = plt.figure() plt.plot(np.rand(100)) display(f) ipython and ipython notebook for matlab users IPython Notebook web-based interface \u00b6 Start with: ipython notebook and switch to browser Keyboard shortcuts: Enter to edit a cell Shift + Enter to evaluate Ctrl + m or Esc for the \"command mode\" In command mode: h list of keyboard shortcuts 1-6 to convert to heading cell m to convert to markdown cell y to convert to code c copy / v paste d d delete cell s save notebook . to restart kernel Papermill \u00b6 Papermill Papermill is a tool for parameterizing and executing Jupyter Notebooks. Papermill GitHub","title":"IPython / Jupyter Cheatsheet"},{"location":"Python/Jupyter/#ipython--jupyter","text":"Using IPython makes interactive work easy. Better shell Notebook interface Embeddable kernel Parallel python","title":"IPython / Jupyter"},{"location":"Python/Jupyter/#ipython-shell-shortcuts","text":"TAB expansion to complete python names and file paths ~ and * directory / file expansion many \"magic\" methods: %lsmagic # list of all magic methods %quickref # cheatsheet %magic","title":"IPython shell shortcuts"},{"location":"Python/Jupyter/#help","text":"? # overall help help # python help system ?someobj or someobj? # help ??someobj or someobj?? # detailed help %pdoc %pdef %psource for docstring, function definition, source code only.","title":"Help"},{"location":"Python/Jupyter/#run","text":"To run a program directly from the IPython console: %run somescript.py # instead of execfile(\"somescript.py\") at the python prompt %run has special flags for timing the execution of your scripts ( -t ) or for running them under the control of either Python's pdb debugger ( -d ) or profiler ( -p ): %run -d myscript.py","title":"Run"},{"location":"Python/Jupyter/#other-commands","text":"%edit %ed # edit then execute %save %load example.py # load local (example) file (or url) allowing modification %load http://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py %macro # define macro with range of history lines, filenames or string objects %recall %whos # list identifiers you have defined interactively %reset -f -s # remove objects -f for force -s for soft (leaves history). %reset is not a kernel restart Restart with Ctrl+. in \"qtconsole\" import module ; reload(module) to reload a module from disk","title":"Other Commands"},{"location":"Python/Jupyter/#debugging","text":"%debug # jump into the Python debugger (pdb) %pdb # start the debugger on any uncaught exception. %cd # change directory %pwd # print working directory %env # OS environment variables","title":"Debugging"},{"location":"Python/Jupyter/#os-commands","text":"!OScommand !ping www.bbc.co.uk %alias # system command alias","title":"OS Commands"},{"location":"Python/Jupyter/#history","text":"_ __ ___ # etc... for previous outputs. _i _ii _i4 # etc.. for previous input. _ih for list of previous inputs","title":"History"},{"location":"Python/Jupyter/#gui-integration","text":"Start with ipython --gui=qt or at the IPython prompt: %gui wx Arguments can be wx , qt , gtk and tk .","title":"GUI integration"},{"location":"Python/Jupyter/#matplotlib--pylab-graphics-in-an-ipython-shell","text":"Start with: ipython --matplotlib ( or --matplotlib=qt etc...) At the IPython prompt: %matplotlib # set matplotlib to work interactively; does not import anythig %matplotlib inline %matplotlib qt # request a specific GUI backend %pylab inline %pylab makes the following imports: import numpy import matplotlib from matplotlib import pylab , mlab , pyplot np = numpy plt = pyplot from IPython.display import display from IPython.core.pylabtools import figsize , getfigs from pylab import * from numpy import *","title":"Matplotlib / pylab graphics in an iPython shell"},{"location":"Python/Jupyter/#qtconsole---an-improved-console","text":"At the command prompt: ipython.exe qtconsole --pylab=inline --ConsoleWidget.font_size=10 alternative: --matplotlib inline or within IPython: %matplotlib inline %pylab inline To embed plots, SVG or HTML in qtconsole, call display: from IPython.core.display import display, display_html from IPython.core.display import display_png, display_svg display(plt.gcf()) # embeds the current figure in the qtconsole display(*getfigs()) # embeds all active figures in the qtconsole #or: f = plt.figure() plt.plot(np.rand(100)) display(f) ipython and ipython notebook for matlab users","title":"Qtconsole - an improved console"},{"location":"Python/Jupyter/#ipython-notebook-web-based-interface","text":"Start with: ipython notebook and switch to browser Keyboard shortcuts: Enter to edit a cell Shift + Enter to evaluate Ctrl + m or Esc for the \"command mode\" In command mode: h list of keyboard shortcuts 1-6 to convert to heading cell m to convert to markdown cell y to convert to code c copy / v paste d d delete cell s save notebook . to restart kernel","title":"IPython Notebook web-based interface"},{"location":"Python/Jupyter/#papermill","text":"Papermill Papermill is a tool for parameterizing and executing Jupyter Notebooks. Papermill GitHub","title":"Papermill"},{"location":"Python/Matplotlib/","text":"Matplotlib Cheatsheet \u00b6 Matplotlib prepares 2D (and some 3D) graphics. Main page: http://www.matplotlib.org Image gallery: http://matplotlib.org/gallery.html pyplot command summary: http://matplotlib.org/api/pyplot_summary.html Examples http://matplotlib.org/examples/index.html Tutorial: http://www.loria.fr/~rougier/teaching/matplotlib/ See also: https://www.wakari.io/nb/url///wakari.io/static/notebooks/Lecture_4_Matplotlib.ipynb Matplotlib, pylab, and pyplot: how are they related? \u00b6 Matplotlib is the whole package. Pylab and matplotlib.pyplot (pyplot in the following) are modules in matplotlib. Pyplot makes matplotlib work like MATLAB. Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module). Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc.... Pyplot is stateful , in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes. Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like. The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting). The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing. Examples \u00b6 import numpy as np import matplotlib.pyplot as plt # Compute the x and y coordinates for points on sine and cosine curves x = np . arange ( 0 , 3 * np . pi , 0.1 ) y_sin = np . sin ( x ) y_cos = np . cos ( x ) # Set up a subplot grid that has height 2 and width 1, # and set the first such subplot as active. plt . subplot ( 2 , 1 , 1 ) # Make the first plot plt . plot ( x , y_sin ) plt . title ( 'Sine' ) # Set the second subplot as active, and make the second plot. plt . subplot ( 2 , 1 , 2 ) plt . plot ( x , y_cos ) plt . title ( 'Cosine' ) # Show the figure. plt . show ()","title":"Matplotlib Cheatsheet"},{"location":"Python/Matplotlib/#matplotlib-cheatsheet","text":"Matplotlib prepares 2D (and some 3D) graphics. Main page: http://www.matplotlib.org Image gallery: http://matplotlib.org/gallery.html pyplot command summary: http://matplotlib.org/api/pyplot_summary.html Examples http://matplotlib.org/examples/index.html Tutorial: http://www.loria.fr/~rougier/teaching/matplotlib/ See also: https://www.wakari.io/nb/url///wakari.io/static/notebooks/Lecture_4_Matplotlib.ipynb","title":"Matplotlib Cheatsheet"},{"location":"Python/Matplotlib/#matplotlib-pylab-and-pyplot-how-are-they-related","text":"Matplotlib is the whole package. Pylab and matplotlib.pyplot (pyplot in the following) are modules in matplotlib. Pyplot makes matplotlib work like MATLAB. Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module). Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc.... Pyplot is stateful , in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes. Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like. The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting). The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing.","title":"Matplotlib, pylab, and pyplot: how are they related?"},{"location":"Python/Matplotlib/#examples","text":"import numpy as np import matplotlib.pyplot as plt # Compute the x and y coordinates for points on sine and cosine curves x = np . arange ( 0 , 3 * np . pi , 0.1 ) y_sin = np . sin ( x ) y_cos = np . cos ( x ) # Set up a subplot grid that has height 2 and width 1, # and set the first such subplot as active. plt . subplot ( 2 , 1 , 1 ) # Make the first plot plt . plot ( x , y_sin ) plt . title ( 'Sine' ) # Set the second subplot as active, and make the second plot. plt . subplot ( 2 , 1 , 2 ) plt . plot ( x , y_cos ) plt . title ( 'Cosine' ) # Show the figure. plt . show ()","title":"Examples"},{"location":"Python/Python/","text":"Python useful links \u00b6 Python environments \u00b6 venv \u2014 Creation of virtual environments python3 -m venv /path/to/new/virtual/environment Virtualenv virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.). pip-tools A set of command line tools to help you keep your pip-based packages fresh, even when you've pinned them. Pipenv The problems that Pipenv seeks to solve are multi-faceted: You no longer need to use pip and virtualenv separately. They work together. Managing a requirements.txt file can be problematic, so Pipenv uses Pipfile and Pipfile.lock to separate abstract dependency declarations from the last tested combination. Hashes are used everywhere, always. Security. Automatically expose security vulnerabilities. Strongly encourage the use of the latest versions of dependencies to minimize security risks arising from outdated components. Give you insight into your dependency graph (e.g. $ pipenv graph). Streamline development workflow by loading .env files. Pyenv for managing multiple Python versions Testing \u00b6 Mockito Code coverage measurement for Python mechanize - Automate interaction with HTTP web servers Packaging \u00b6 Cookiecutter template for a Python package Python Packaging User Guide Twine Twine is a utility for publishing Python packages on PyPI. Build tools \u00b6 Buildout, an automation tool written in and extended with Python PyBuilder Uranium: a Python Build System Other \u00b6 Python Anywhere Host, run, and code Python in the cloud","title":"Python Links"},{"location":"Python/Python/#python-useful-links","text":"","title":"Python useful links"},{"location":"Python/Python/#python-environments","text":"venv \u2014 Creation of virtual environments python3 -m venv /path/to/new/virtual/environment Virtualenv virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.). pip-tools A set of command line tools to help you keep your pip-based packages fresh, even when you've pinned them. Pipenv The problems that Pipenv seeks to solve are multi-faceted: You no longer need to use pip and virtualenv separately. They work together. Managing a requirements.txt file can be problematic, so Pipenv uses Pipfile and Pipfile.lock to separate abstract dependency declarations from the last tested combination. Hashes are used everywhere, always. Security. Automatically expose security vulnerabilities. Strongly encourage the use of the latest versions of dependencies to minimize security risks arising from outdated components. Give you insight into your dependency graph (e.g. $ pipenv graph). Streamline development workflow by loading .env files. Pyenv for managing multiple Python versions","title":"Python environments"},{"location":"Python/Python/#testing","text":"Mockito Code coverage measurement for Python mechanize - Automate interaction with HTTP web servers","title":"Testing"},{"location":"Python/Python/#packaging","text":"Cookiecutter template for a Python package Python Packaging User Guide Twine Twine is a utility for publishing Python packages on PyPI.","title":"Packaging"},{"location":"Python/Python/#build-tools","text":"Buildout, an automation tool written in and extended with Python PyBuilder Uranium: a Python Build System","title":"Build tools"},{"location":"Python/Python/#other","text":"Python Anywhere Host, run, and code Python in the cloud","title":"Other"},{"location":"Python/Python3/","text":"What's new in Python 3.x \u00b6 What's really new in Python 3 nonlocal / global \u00b6 x = 0 def outer (): x = 1 def inner (): nonlocal x x = 2 print ( \"inner:\" , x ) inner () print ( \"outer:\" , x ) outer () print ( \"global:\" , x ) # inner: 2 # outer: 2 # global: 0 ## with global x = 0 def outer (): x = 1 def inner (): global x x = 2 print ( \"inner:\" , x ) inner () print ( \"outer:\" , x ) outer () print ( \"global:\" , x ) # inner: 2 # outer: 1 # global: 2 String interpolation - new in 3.6 \u00b6 name = \"David\" f \"My name is { name } \" value = decimal . Decimal ( \"10.4507\" ) print ( f \"result: { value : 10.5 } \" ) # width precision PEP 492 - Coroutines with async and await syntax \u00b6 async and await yield from iterator is equivalent for x in iterator : yield x Example: def lazy_range ( up_to ): \"\"\"Generator to return the sequence of integers from 0 to up_to, exclusive.\"\"\" index = 0 def gratuitous_refactor (): nonlocal index while index < up_to : yield index index += 1 yield from gratuitous_refactor () New 3.6 syntax: async def func ( param1 , param2 ): do_stuff () await some_coroutine () async def read_data ( db ): data = await db . fetch ( 'SELECT ...' ) async def display_date ( loop ): end_time = loop . time () + 5.0 while True : print ( datetime . datetime . now ()) if ( loop . time () + 1.0 ) >= end_time : break await asyncio . sleep ( 1 ) loop = asyncio . get_event_loop () # Blocking call which returns when the display_date() coroutine is done loop . run_until_complete ( display_date ( loop )) loop . close () Async for \u00b6 async for TARGET in ITER : BLOCK else : BLOCK2 Async improvements - 3.6 \u00b6 set comprehension: {i async for i in agen()} list comprehension: [i async for i in agen()] dict comprehension: {i: i ** 2 async for i in agen()} generator expression: (i ** 2 async for i in agen()) Type hinting \u00b6 PEP 484 mypy-lang.org def greet ( name : str ) -> str return 'Hello there, {} ' . format ( name ) Type aliases \u00b6 Url = str def retry ( url : Url , retry_count : int ) -> None : ... from typing import TypeVar , Iterable , Tuple Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int] T = TypeVar ( 'T' , int , float , complex ) # T is either or an int, a float or a complex Vector = Iterable [ Tuple [ T , T ]] # def inproduct ( v : Vector [ T ]) -> T : return sum ( x * y for x , y in v ) def dilate ( v : Vector [ T ], scale : T ) -> Vector [ T ]: return (( x * scale , y * scale ) for x , y in v ) vec = [] # type: Vector[float] For functions \u00b6 Callable [[ Arg1Type , Arg2Type ], ReturnType ] Type comments \u00b6 x = [] # type: List[Employee] x , y , z = [], [], [] # type: List[int], List[int], List[str]","title":"Python 3"},{"location":"Python/Python3/#whats-new-in-python-3x","text":"What's really new in Python 3","title":"What's new in Python 3.x"},{"location":"Python/Python3/#nonlocal--global","text":"x = 0 def outer (): x = 1 def inner (): nonlocal x x = 2 print ( \"inner:\" , x ) inner () print ( \"outer:\" , x ) outer () print ( \"global:\" , x ) # inner: 2 # outer: 2 # global: 0 ## with global x = 0 def outer (): x = 1 def inner (): global x x = 2 print ( \"inner:\" , x ) inner () print ( \"outer:\" , x ) outer () print ( \"global:\" , x ) # inner: 2 # outer: 1 # global: 2","title":"nonlocal / global"},{"location":"Python/Python3/#string-interpolation---new-in-36","text":"name = \"David\" f \"My name is { name } \" value = decimal . Decimal ( \"10.4507\" ) print ( f \"result: { value : 10.5 } \" ) # width precision","title":"String interpolation - new in 3.6"},{"location":"Python/Python3/#pep-492---coroutines-with-async-and-await-syntax","text":"async and await yield from iterator is equivalent for x in iterator : yield x Example: def lazy_range ( up_to ): \"\"\"Generator to return the sequence of integers from 0 to up_to, exclusive.\"\"\" index = 0 def gratuitous_refactor (): nonlocal index while index < up_to : yield index index += 1 yield from gratuitous_refactor () New 3.6 syntax: async def func ( param1 , param2 ): do_stuff () await some_coroutine () async def read_data ( db ): data = await db . fetch ( 'SELECT ...' ) async def display_date ( loop ): end_time = loop . time () + 5.0 while True : print ( datetime . datetime . now ()) if ( loop . time () + 1.0 ) >= end_time : break await asyncio . sleep ( 1 ) loop = asyncio . get_event_loop () # Blocking call which returns when the display_date() coroutine is done loop . run_until_complete ( display_date ( loop )) loop . close ()","title":"PEP 492 - Coroutines with async and await syntax"},{"location":"Python/Python3/#async-for","text":"async for TARGET in ITER : BLOCK else : BLOCK2","title":"Async for"},{"location":"Python/Python3/#async-improvements---36","text":"set comprehension: {i async for i in agen()} list comprehension: [i async for i in agen()] dict comprehension: {i: i ** 2 async for i in agen()} generator expression: (i ** 2 async for i in agen())","title":"Async improvements - 3.6"},{"location":"Python/Python3/#type-hinting","text":"PEP 484 mypy-lang.org def greet ( name : str ) -> str return 'Hello there, {} ' . format ( name )","title":"Type hinting"},{"location":"Python/Python3/#type-aliases","text":"Url = str def retry ( url : Url , retry_count : int ) -> None : ... from typing import TypeVar , Iterable , Tuple Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int] T = TypeVar ( 'T' , int , float , complex ) # T is either or an int, a float or a complex Vector = Iterable [ Tuple [ T , T ]] # def inproduct ( v : Vector [ T ]) -> T : return sum ( x * y for x , y in v ) def dilate ( v : Vector [ T ], scale : T ) -> Vector [ T ]: return (( x * scale , y * scale ) for x , y in v ) vec = [] # type: Vector[float]","title":"Type aliases"},{"location":"Python/Python3/#for-functions","text":"Callable [[ Arg1Type , Arg2Type ], ReturnType ]","title":"For functions"},{"location":"Python/Python3/#type-comments","text":"x = [] # type: List[Employee] x , y , z = [], [], [] # type: List[int], List[int], List[str]","title":"Type comments"},{"location":"Scala/Akka/","text":"Akka \u00b6 Actors have: A mailbox (the queue where messages end up). A behavior (the state of the actor, internal variables etc.). Messages (pieces of data representing a signal, similar to method calls and their parameters). An execution environment (the machinery that takes actors that have messages to react to and invokes their message handling code). An address. sbt: libraryDependencies ++= Seq ( \"com.typesafe.akka\" %% \"akka-actor\" % \"2.5.6\" , \"com.typesafe.akka\" %% \"akka-testkit\" % \"2.5.6\" % Test ) Basic Example \u00b6 //#full-example package com.lightbend.akka.sample import akka.actor. { Actor , ActorLogging , ActorRef , ActorSystem , Props } import scala.io.StdIn //#greeter-companion //#greeter-messages object Greeter { //#greeter-messages def props ( message : String , printerActor : ActorRef ) : Props = Props ( new Greeter ( message , printerActor )) //#greeter-messages final case class WhoToGreet ( who : String ) case object Greet } //#greeter-messages //#greeter-companion //#greeter-actor class Greeter ( message : String , printerActor : ActorRef ) extends Actor { import Greeter._ import Printer._ var greeting = \"\" def receive = { case WhoToGreet ( who ) => greeting = s\" $message , $who \" case Greet => //#greeter-send-message printerActor ! Greeting ( greeting ) //#greeter-send-message } } //#greeter-actor //#printer-companion //#printer-messages object Printer { //#printer-messages def props : Props = Props [ Printer ] //#printer-messages final case class Greeting ( greeting : String ) } //#printer-messages //#printer-companion //#printer-actor class Printer extends Actor with ActorLogging { import Printer._ def receive = { case Greeting ( greeting ) => log . info ( s\"Greeting received (from ${ sender () } ): $greeting \" ) } } //#printer-actor //#main-class object AkkaQuickstart extends App { import Greeter._ // Create the 'helloAkka' actor system val system : ActorSystem = ActorSystem ( \"helloAkka\" ) try { //#create-actors // Create the printer actor val printer : ActorRef = system . actorOf ( Printer . props , \"printerActor\" ) // Create the 'greeter' actors val howdyGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Howdy\" , printer ), \"howdyGreeter\" ) val helloGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Hello\" , printer ), \"helloGreeter\" ) val goodDayGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Good day\" , printer ), \"goodDayGreeter\" ) //#create-actors //#main-send-messages howdyGreeter ! WhoToGreet ( \"Akka\" ) howdyGreeter ! Greet howdyGreeter ! WhoToGreet ( \"Lightbend\" ) howdyGreeter ! Greet helloGreeter ! WhoToGreet ( \"Scala\" ) helloGreeter ! Greet goodDayGreeter ! WhoToGreet ( \"Play\" ) goodDayGreeter ! Greet //#main-send-messages println ( \">>> Press ENTER to exit <<<\" ) StdIn . readLine () } finally { system . terminate () } } //#main-class //#full-example","title":"Akka Cheatsheet"},{"location":"Scala/Akka/#akka","text":"Actors have: A mailbox (the queue where messages end up). A behavior (the state of the actor, internal variables etc.). Messages (pieces of data representing a signal, similar to method calls and their parameters). An execution environment (the machinery that takes actors that have messages to react to and invokes their message handling code). An address. sbt: libraryDependencies ++= Seq ( \"com.typesafe.akka\" %% \"akka-actor\" % \"2.5.6\" , \"com.typesafe.akka\" %% \"akka-testkit\" % \"2.5.6\" % Test )","title":"Akka"},{"location":"Scala/Akka/#basic-example","text":"//#full-example package com.lightbend.akka.sample import akka.actor. { Actor , ActorLogging , ActorRef , ActorSystem , Props } import scala.io.StdIn //#greeter-companion //#greeter-messages object Greeter { //#greeter-messages def props ( message : String , printerActor : ActorRef ) : Props = Props ( new Greeter ( message , printerActor )) //#greeter-messages final case class WhoToGreet ( who : String ) case object Greet } //#greeter-messages //#greeter-companion //#greeter-actor class Greeter ( message : String , printerActor : ActorRef ) extends Actor { import Greeter._ import Printer._ var greeting = \"\" def receive = { case WhoToGreet ( who ) => greeting = s\" $message , $who \" case Greet => //#greeter-send-message printerActor ! Greeting ( greeting ) //#greeter-send-message } } //#greeter-actor //#printer-companion //#printer-messages object Printer { //#printer-messages def props : Props = Props [ Printer ] //#printer-messages final case class Greeting ( greeting : String ) } //#printer-messages //#printer-companion //#printer-actor class Printer extends Actor with ActorLogging { import Printer._ def receive = { case Greeting ( greeting ) => log . info ( s\"Greeting received (from ${ sender () } ): $greeting \" ) } } //#printer-actor //#main-class object AkkaQuickstart extends App { import Greeter._ // Create the 'helloAkka' actor system val system : ActorSystem = ActorSystem ( \"helloAkka\" ) try { //#create-actors // Create the printer actor val printer : ActorRef = system . actorOf ( Printer . props , \"printerActor\" ) // Create the 'greeter' actors val howdyGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Howdy\" , printer ), \"howdyGreeter\" ) val helloGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Hello\" , printer ), \"helloGreeter\" ) val goodDayGreeter : ActorRef = system . actorOf ( Greeter . props ( \"Good day\" , printer ), \"goodDayGreeter\" ) //#create-actors //#main-send-messages howdyGreeter ! WhoToGreet ( \"Akka\" ) howdyGreeter ! Greet howdyGreeter ! WhoToGreet ( \"Lightbend\" ) howdyGreeter ! Greet helloGreeter ! WhoToGreet ( \"Scala\" ) helloGreeter ! Greet goodDayGreeter ! WhoToGreet ( \"Play\" ) goodDayGreeter ! Greet //#main-send-messages println ( \">>> Press ENTER to exit <<<\" ) StdIn . readLine () } finally { system . terminate () } } //#main-class //#full-example","title":"Basic Example"},{"location":"Scala/Play_Framework/","text":"Links \u00b6 Play Framework The Play application layout \u00b6 The layout of a Play application is standardized to keep things as simple as possible. After a first successful compile, a Play application looks like this: app \u2192 Application sources \u2514 assets \u2192 Compiled asset sources \u2514 stylesheets \u2192 Typically LESS CSS sources \u2514 javascripts \u2192 Typically CoffeeScript sources \u2514 controllers \u2192 Application controllers \u2514 models \u2192 Application business layer \u2514 views \u2192 Templates build.sbt \u2192 Application build script conf \u2192 Configurations files and other non-compiled resources (on classpath) \u2514 application.conf \u2192 Main configuration file \u2514 routes \u2192 Routes definition dist \u2192 Arbitrary files to be included in your projects distribution public \u2192 Public assets \u2514 stylesheets \u2192 CSS files \u2514 javascripts \u2192 Javascript files \u2514 images \u2192 Image files project \u2192 sbt configuration files \u2514 build.properties \u2192 Marker for sbt project \u2514 plugins.sbt \u2192 sbt plugins including the declaration for Play itself lib \u2192 Unmanaged libraries dependencies logs \u2192 Logs folder \u2514 application.log \u2192 Default log file target \u2192 Generated stuff \u2514 resolution-cache \u2192 Info about dependencies \u2514 scala-2.11 \u2514 api \u2192 Generated API docs \u2514 classes \u2192 Compiled class files \u2514 routes \u2192 Sources generated from routes \u2514 twirl \u2192 Sources generated from templates \u2514 universal \u2192 Application packaging \u2514 web \u2192 Compiled web assets test \u2192 source folder for unit or functional tests","title":"Play Framework"},{"location":"Scala/Play_Framework/#links","text":"Play Framework","title":"Links"},{"location":"Scala/Play_Framework/#the-play-application-layout","text":"The layout of a Play application is standardized to keep things as simple as possible. After a first successful compile, a Play application looks like this: app \u2192 Application sources \u2514 assets \u2192 Compiled asset sources \u2514 stylesheets \u2192 Typically LESS CSS sources \u2514 javascripts \u2192 Typically CoffeeScript sources \u2514 controllers \u2192 Application controllers \u2514 models \u2192 Application business layer \u2514 views \u2192 Templates build.sbt \u2192 Application build script conf \u2192 Configurations files and other non-compiled resources (on classpath) \u2514 application.conf \u2192 Main configuration file \u2514 routes \u2192 Routes definition dist \u2192 Arbitrary files to be included in your projects distribution public \u2192 Public assets \u2514 stylesheets \u2192 CSS files \u2514 javascripts \u2192 Javascript files \u2514 images \u2192 Image files project \u2192 sbt configuration files \u2514 build.properties \u2192 Marker for sbt project \u2514 plugins.sbt \u2192 sbt plugins including the declaration for Play itself lib \u2192 Unmanaged libraries dependencies logs \u2192 Logs folder \u2514 application.log \u2192 Default log file target \u2192 Generated stuff \u2514 resolution-cache \u2192 Info about dependencies \u2514 scala-2.11 \u2514 api \u2192 Generated API docs \u2514 classes \u2192 Compiled class files \u2514 routes \u2192 Sources generated from routes \u2514 twirl \u2192 Sources generated from templates \u2514 universal \u2192 Application packaging \u2514 web \u2192 Compiled web assets test \u2192 source folder for unit or functional tests","title":"The Play application layout"},{"location":"Scala/Scala_Collections/","text":"Examples from Scala Koans . Core Packages \u00b6 The scala package contains core types like Int, Float, Array or Option which are accessible in all Scala compilation units without explicit qualification or imports. Notable packages include: scala.collection and its sub-packages contain Scala's collections framework scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet scala.concurrent - Primitives for concurrent programming such as Futures and Promises scala.io - Input and output operations scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal scala.sys - Interaction with other processes and the operating system scala.util.matching - Regular expressions Additional parts of the standard library are shipped as separate libraries. These include: scala.reflect - Scala's reflection API (scala-reflect.jar) scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar) scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) scala.util.parsing - Parser combinators (scala-parser-combinators.jar) Automatic imports Identifiers in the scala package and the scala.Predef object are always in scope by default. Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.List. Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String. Traversables \u00b6 Traversables are the superclass of Lists, Arrays, Maps, Sets, Streams, and more. The methods involved can be applied to each other in a different type. val set = Set ( 1 , 9 , 10 , 22 ) val list = List ( 3 , 4 , 5 , 10 ) val result = set ++ list // ++ appends two Traversables together. result . size result . isEmpty result . hasDefiniteSize // false if a Stream Take some list . head list . headOption list . tail list . lastOption result . last list . init // collection without the last element list . slice ( 1 , 3 ) list . take ( 3 ) list drop 6 take 3 list . takeWhile ( _ < 100 ) list . dropWhile ( _ < 100 ) Filter, Map, Flatten list . filter ( _ < 100 ) list . filterNot ( _ < 100 ) list . find ( _ % 2 != 0 ) // get first element that matches list . foreach ( num => println ( num * 4 )) // side effect list . map ( _ * 4 ) // map val list = List ( List ( 1 ), List ( 2 , 3 , 4 ), List ( 5 , 6 , 7 ), List ( 8 , 9 , 10 )) list . flatten list . flatMap ( _ . map ( _ * 4 )) // map then flatten val result = list . collect { // apply a partial function to all elements of a Traversable and will return a different collection. case x : Int if ( x % 2 == 0 ) => x * 3 } // can use orElse or andThen Split val array = Array ( 87 , 44 , 5 , 4 , 200 , 10 , 39 , 100 ) // splitAt - will split a Traversable at a position, returning a tuple. val result = array splitAt 3 result . _1 result . _2 val result = array partition ( _ < 100 ) // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not. // groupBy returns a map e.g. Map( \"Odd\" -> ... , \"Even\" -> ...) val result = array groupBy { case x : Int if x % 2 == 0 => \"Even\" ; case x : Int if x % 2 != 0 => \"Odd\" } Analyze list forall ( _ < 100 ) // true if predicate true for all elements list exists ( _ < 100 ) // true if predicate true for any element list count ( _ < 100 ) Reduce and Fold list . foldLeft ( 0 )( _ - _ ) ( 0 /: list )( _ - _ ) // Short hand list . foldRight ( 0 )( _ - _ ) ( list :\\ 0 )( _ - _ ) // Short hand list . reduceLeft { _ + _ } list . reduceRight { _ + _ } list . sum list . product list . max list . min val list = List ( List ( 1 , 2 , 3 ), List ( 4 , 5 , 6 ), List ( 7 , 8 , 9 )) list . transpose Conversions; toList, as well as other conversion methods like toSet, toArray will not convert if the collection type is the same. list . toArray list . toSet set . toList set . toIterable set . toSeq set . toIndexedSeq list . toStream val list = List ( \"Phoenix\" -> \"Arizona\" , \"Austin\" -> \"Texas\" ) // elements should be tuples val result = list . toMap Print result . mkString ( \",\" ) list . mkString ( \">\" , \",\" , \"<\" ) val list = List ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) stringBuilder . append ( \"I want all numbers 6-12: \" ) list . filter ( it => it > 5 && it < 13 ). addString ( stringBuilder , \",\" ) stringBuilder . mkString Lists \u00b6 val a = List ( 1 , 2 , 3 ) // immutable val b = 1 :: 2 :: 3 :: Nil // cons notation ( a == b ) // true a eq b // false a . length a . head a . tail a . reverse // reverse the list a . map { v => v * 2 } // or a.map {_ * 2} or a.map(_ * 2) a . filter { v => v % 3 == 0 } a . filterNot ( v => v == 5 ) // remove where value is 5 a . reduceLeft ( _ + _ ) // note the two _s below indicate the first and second args respectively a . foldLeft ( 10 )( _ + _ ) // foldlLeft is like reduce, but with an explicit starting value ( 1 to 5 ). toList // from range val a = a . toArray Nil lists are identical, even of different types Iterators \u00b6 val list = List ( 3 , 5 , 9 , 11 , 15 , 19 , 21 ) val it = list . iterator if ( it . hasNext ) { it . next should be ( __ ) } val it = list grouped 3 // `grouped` will return an fixed sized Iterable chucks of an Iterable val it = list sliding 3 // `sliding` will return an Iterable that shows a sliding window of an Iterable. val it = list sliding ( 3 , 3 ) // `sliding` can take the size of the window as well the size of the step during each iteration list takeRight 3 list dropRight 3 val xs = List ( 3 , 5 , 9 ) // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables. val ys = List ( \"Bob\" , \"Ann\" , \"Stella\" ) xs zip ys // If two Iterables aren't the same size, then `zip` will only zip what can only be paired. xs zipAll ( ys , - 1 , \"?\" ) // if two Iterables aren't the same size, then `zipAll` can provide fillers xs . zipWithIndex Arrays, Sequences \u00b6 val a = Array ( 1 , 2 , 3 ) val s = a . toSeq val l = s . toList val s = Seq ( \"hello\" , \"to\" , \"you\" ) val filtered = s . filter ( _ . length > 2 ) val r = s map { _ . reverse } val s = for ( v <- 1 to 10 if v % 3 == 0 ) yield v // create a sequence from a for comprehension with an optional condition s . toList Lazy Collections and Streams \u00b6 val strictList = List ( 10 , 20 , 30 ) val lazyList = strictList . view // Strict collection always processes its elements but lazy collection does it on demand val infinite = Stream . from ( 1 ) infinite . take ( 4 ). sum Stream . continually ( 1 ). take ( 4 ). sum // Always remember tail of a lazy collection is never computed unless required def makeLazy ( value : Int ) : Stream [ Int ] = { Stream . cons ( value , makeLazy ( value + 1 )) } val stream = makeLazy ( 1 ) stream . head Maps \u00b6 val myMap = Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"MI\" -> \"Michigan\" ) // access by key - Accessing a map by key results in an exception if key is not found myMap ( \"MI\" ) myMap . contains ( \"IL\" ) val aNewMap = myMap + ( \"IL\" -> \"Illinois\" ) // add - creates a new collection if immutable val aNewMap = myMap - \"MI\" // remove - Attempted removal of nonexistent elements from a map is handled gracefully val aNewMap = myMap -- List ( \"MI\" , \"OH\" ) // remove multiples val aNewMap = myMap - ( \"MI\" , \"WI\" ) // Notice: single '-' operator for tuples var anotherMap += ( \"IL\" -> \"Illinois\" ) // compiler trick - creates a new collection and reassigns; note the 'var' // Map values can be iterated val mapValues = myMap . values mapValues . size mapValues . head mapValues . last for ( mval <- mapValues ) println ( mval ) // NOTE that the following will not compile, as iterators do not implement \"contains\" //mapValues.contains(\"Illinois\") // Map keys may be of mixed type val myMap = Map ( \"Ann Arbor\" -> \"MI\" , 49931 -> \"MI\" ) // Mixed type values can be added to a map val myMap = scala . collection . mutable . Map . empty [ String , Any ] myMap ( \"Ann Arbor\" ) = ( 48103 , 48104 , 48108 ) myMap ( \"Houghton\" ) = 49931 // Map equivalency is independent of order val myMap1 = Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"IA\" -> \"Iowa\" ) val myMap2 = Map ( \"WI\" -> \"Wisconsin\" , \"MI\" -> \"Michigan\" , \"IA\" -> \"Iowa\" , \"OH\" -> \"Ohio\" ) myMap1 . equals ( myMap2 ) Maps insertion with duplicate key updates previous entry with subsequent value Mutable Maps val myMap = mutable . Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"IA\" -> \"Iowa\" ) // same methods than immutable maps work val myMap += ( \"IL\" -> \"Illinois\" ) // this is a method; note the difference from immutable += myMap . clear () // Convention is to use parens if possible when method called changes state Sets \u00b6 val mySet = Set ( 1 , 3 , 4 , 9 ) // immutable val mySet = mutable . Set ( \"Michigan\" , \"Ohio\" , \"Wisconsin\" , \"Iowa\" ) mySet . size mySet contains \"Ohio\" mySet += \"Oregon\" mySet += ( \"Iowa\" , \"Ohio\" ) mySet ++= List ( \"Iowa\" , \"Ohio\" ) mySet -= \"Ohio\" mySet --= List ( \"Iowa\" , \"Ohio\" ) mySet . clear () // mutable only var sum = 0 for ( i <- mySet ) // for comprehension sum = sum + i // of course this is the same thing as mySet.reduce(_ + _) val mySet2 = Set ( \"Wisconsin\" , \"Michigan\" , \"Minnesota\" ) mySet intersect mySet2 // or & operator mySet1 union mySet2 // or | operator mySet2 subsetOf mySet1 mySet1 diff mySet2 mySet1 . equals ( mySet2 ) // independent of order Option[T] \u00b6 val someValue : Option [ String ] = Some ( \"I am wrapped in something\" ) val nullValue : Option [ String ] = None someValue . get // java.util.NoSuchElementException if None nullValue getOrElse \"No value\" nullValue . isEmpty val value = someValue match { // pattern matching case Some ( v ) => v case None => 0.0 } Option is more than just a replacement of null, its also a collection. Some ( 10 ) filter { _ == 10 } Some ( Some ( 10 )) flatMap { _ map { _ + 10 }} var newValue1 = 0 Some ( 20 ) foreach { newValue1 = _ } flatMap of Options will filter out all Nones and keep the Somes val list = List ( 1 , 2 , 3 , 4 , 5 ) val result = list . flatMap ( it => if ( it % 2 == 0 ) Some ( it ) else None ) Using \"for comprehension\" val values = List ( Some ( 10 ), Some ( 20 ), None , Some ( 15 )) val newValues = for { someValue <- values value <- someValue } yield value Java Interop \u00b6 Scala can implicitly convert from a Scala collection type into a Java collection type. import scala.collection.JavaConversions._","title":"Scala Collections"},{"location":"Scala/Scala_Collections/#core-packages","text":"The scala package contains core types like Int, Float, Array or Option which are accessible in all Scala compilation units without explicit qualification or imports. Notable packages include: scala.collection and its sub-packages contain Scala's collections framework scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet scala.concurrent - Primitives for concurrent programming such as Futures and Promises scala.io - Input and output operations scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal scala.sys - Interaction with other processes and the operating system scala.util.matching - Regular expressions Additional parts of the standard library are shipped as separate libraries. These include: scala.reflect - Scala's reflection API (scala-reflect.jar) scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar) scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) scala.util.parsing - Parser combinators (scala-parser-combinators.jar) Automatic imports Identifiers in the scala package and the scala.Predef object are always in scope by default. Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.List. Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String.","title":"Core Packages"},{"location":"Scala/Scala_Collections/#traversables","text":"Traversables are the superclass of Lists, Arrays, Maps, Sets, Streams, and more. The methods involved can be applied to each other in a different type. val set = Set ( 1 , 9 , 10 , 22 ) val list = List ( 3 , 4 , 5 , 10 ) val result = set ++ list // ++ appends two Traversables together. result . size result . isEmpty result . hasDefiniteSize // false if a Stream Take some list . head list . headOption list . tail list . lastOption result . last list . init // collection without the last element list . slice ( 1 , 3 ) list . take ( 3 ) list drop 6 take 3 list . takeWhile ( _ < 100 ) list . dropWhile ( _ < 100 ) Filter, Map, Flatten list . filter ( _ < 100 ) list . filterNot ( _ < 100 ) list . find ( _ % 2 != 0 ) // get first element that matches list . foreach ( num => println ( num * 4 )) // side effect list . map ( _ * 4 ) // map val list = List ( List ( 1 ), List ( 2 , 3 , 4 ), List ( 5 , 6 , 7 ), List ( 8 , 9 , 10 )) list . flatten list . flatMap ( _ . map ( _ * 4 )) // map then flatten val result = list . collect { // apply a partial function to all elements of a Traversable and will return a different collection. case x : Int if ( x % 2 == 0 ) => x * 3 } // can use orElse or andThen Split val array = Array ( 87 , 44 , 5 , 4 , 200 , 10 , 39 , 100 ) // splitAt - will split a Traversable at a position, returning a tuple. val result = array splitAt 3 result . _1 result . _2 val result = array partition ( _ < 100 ) // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not. // groupBy returns a map e.g. Map( \"Odd\" -> ... , \"Even\" -> ...) val result = array groupBy { case x : Int if x % 2 == 0 => \"Even\" ; case x : Int if x % 2 != 0 => \"Odd\" } Analyze list forall ( _ < 100 ) // true if predicate true for all elements list exists ( _ < 100 ) // true if predicate true for any element list count ( _ < 100 ) Reduce and Fold list . foldLeft ( 0 )( _ - _ ) ( 0 /: list )( _ - _ ) // Short hand list . foldRight ( 0 )( _ - _ ) ( list :\\ 0 )( _ - _ ) // Short hand list . reduceLeft { _ + _ } list . reduceRight { _ + _ } list . sum list . product list . max list . min val list = List ( List ( 1 , 2 , 3 ), List ( 4 , 5 , 6 ), List ( 7 , 8 , 9 )) list . transpose Conversions; toList, as well as other conversion methods like toSet, toArray will not convert if the collection type is the same. list . toArray list . toSet set . toList set . toIterable set . toSeq set . toIndexedSeq list . toStream val list = List ( \"Phoenix\" -> \"Arizona\" , \"Austin\" -> \"Texas\" ) // elements should be tuples val result = list . toMap Print result . mkString ( \",\" ) list . mkString ( \">\" , \",\" , \"<\" ) val list = List ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) stringBuilder . append ( \"I want all numbers 6-12: \" ) list . filter ( it => it > 5 && it < 13 ). addString ( stringBuilder , \",\" ) stringBuilder . mkString","title":"Traversables"},{"location":"Scala/Scala_Collections/#lists","text":"val a = List ( 1 , 2 , 3 ) // immutable val b = 1 :: 2 :: 3 :: Nil // cons notation ( a == b ) // true a eq b // false a . length a . head a . tail a . reverse // reverse the list a . map { v => v * 2 } // or a.map {_ * 2} or a.map(_ * 2) a . filter { v => v % 3 == 0 } a . filterNot ( v => v == 5 ) // remove where value is 5 a . reduceLeft ( _ + _ ) // note the two _s below indicate the first and second args respectively a . foldLeft ( 10 )( _ + _ ) // foldlLeft is like reduce, but with an explicit starting value ( 1 to 5 ). toList // from range val a = a . toArray Nil lists are identical, even of different types","title":"Lists"},{"location":"Scala/Scala_Collections/#iterators","text":"val list = List ( 3 , 5 , 9 , 11 , 15 , 19 , 21 ) val it = list . iterator if ( it . hasNext ) { it . next should be ( __ ) } val it = list grouped 3 // `grouped` will return an fixed sized Iterable chucks of an Iterable val it = list sliding 3 // `sliding` will return an Iterable that shows a sliding window of an Iterable. val it = list sliding ( 3 , 3 ) // `sliding` can take the size of the window as well the size of the step during each iteration list takeRight 3 list dropRight 3 val xs = List ( 3 , 5 , 9 ) // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables. val ys = List ( \"Bob\" , \"Ann\" , \"Stella\" ) xs zip ys // If two Iterables aren't the same size, then `zip` will only zip what can only be paired. xs zipAll ( ys , - 1 , \"?\" ) // if two Iterables aren't the same size, then `zipAll` can provide fillers xs . zipWithIndex","title":"Iterators"},{"location":"Scala/Scala_Collections/#arrays-sequences","text":"val a = Array ( 1 , 2 , 3 ) val s = a . toSeq val l = s . toList val s = Seq ( \"hello\" , \"to\" , \"you\" ) val filtered = s . filter ( _ . length > 2 ) val r = s map { _ . reverse } val s = for ( v <- 1 to 10 if v % 3 == 0 ) yield v // create a sequence from a for comprehension with an optional condition s . toList","title":"Arrays, Sequences"},{"location":"Scala/Scala_Collections/#lazy-collections-and-streams","text":"val strictList = List ( 10 , 20 , 30 ) val lazyList = strictList . view // Strict collection always processes its elements but lazy collection does it on demand val infinite = Stream . from ( 1 ) infinite . take ( 4 ). sum Stream . continually ( 1 ). take ( 4 ). sum // Always remember tail of a lazy collection is never computed unless required def makeLazy ( value : Int ) : Stream [ Int ] = { Stream . cons ( value , makeLazy ( value + 1 )) } val stream = makeLazy ( 1 ) stream . head","title":"Lazy Collections and Streams"},{"location":"Scala/Scala_Collections/#maps","text":"val myMap = Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"MI\" -> \"Michigan\" ) // access by key - Accessing a map by key results in an exception if key is not found myMap ( \"MI\" ) myMap . contains ( \"IL\" ) val aNewMap = myMap + ( \"IL\" -> \"Illinois\" ) // add - creates a new collection if immutable val aNewMap = myMap - \"MI\" // remove - Attempted removal of nonexistent elements from a map is handled gracefully val aNewMap = myMap -- List ( \"MI\" , \"OH\" ) // remove multiples val aNewMap = myMap - ( \"MI\" , \"WI\" ) // Notice: single '-' operator for tuples var anotherMap += ( \"IL\" -> \"Illinois\" ) // compiler trick - creates a new collection and reassigns; note the 'var' // Map values can be iterated val mapValues = myMap . values mapValues . size mapValues . head mapValues . last for ( mval <- mapValues ) println ( mval ) // NOTE that the following will not compile, as iterators do not implement \"contains\" //mapValues.contains(\"Illinois\") // Map keys may be of mixed type val myMap = Map ( \"Ann Arbor\" -> \"MI\" , 49931 -> \"MI\" ) // Mixed type values can be added to a map val myMap = scala . collection . mutable . Map . empty [ String , Any ] myMap ( \"Ann Arbor\" ) = ( 48103 , 48104 , 48108 ) myMap ( \"Houghton\" ) = 49931 // Map equivalency is independent of order val myMap1 = Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"IA\" -> \"Iowa\" ) val myMap2 = Map ( \"WI\" -> \"Wisconsin\" , \"MI\" -> \"Michigan\" , \"IA\" -> \"Iowa\" , \"OH\" -> \"Ohio\" ) myMap1 . equals ( myMap2 ) Maps insertion with duplicate key updates previous entry with subsequent value Mutable Maps val myMap = mutable . Map ( \"MI\" -> \"Michigan\" , \"OH\" -> \"Ohio\" , \"WI\" -> \"Wisconsin\" , \"IA\" -> \"Iowa\" ) // same methods than immutable maps work val myMap += ( \"IL\" -> \"Illinois\" ) // this is a method; note the difference from immutable += myMap . clear () // Convention is to use parens if possible when method called changes state","title":"Maps"},{"location":"Scala/Scala_Collections/#sets","text":"val mySet = Set ( 1 , 3 , 4 , 9 ) // immutable val mySet = mutable . Set ( \"Michigan\" , \"Ohio\" , \"Wisconsin\" , \"Iowa\" ) mySet . size mySet contains \"Ohio\" mySet += \"Oregon\" mySet += ( \"Iowa\" , \"Ohio\" ) mySet ++= List ( \"Iowa\" , \"Ohio\" ) mySet -= \"Ohio\" mySet --= List ( \"Iowa\" , \"Ohio\" ) mySet . clear () // mutable only var sum = 0 for ( i <- mySet ) // for comprehension sum = sum + i // of course this is the same thing as mySet.reduce(_ + _) val mySet2 = Set ( \"Wisconsin\" , \"Michigan\" , \"Minnesota\" ) mySet intersect mySet2 // or & operator mySet1 union mySet2 // or | operator mySet2 subsetOf mySet1 mySet1 diff mySet2 mySet1 . equals ( mySet2 ) // independent of order","title":"Sets"},{"location":"Scala/Scala_Collections/#optiont","text":"val someValue : Option [ String ] = Some ( \"I am wrapped in something\" ) val nullValue : Option [ String ] = None someValue . get // java.util.NoSuchElementException if None nullValue getOrElse \"No value\" nullValue . isEmpty val value = someValue match { // pattern matching case Some ( v ) => v case None => 0.0 } Option is more than just a replacement of null, its also a collection. Some ( 10 ) filter { _ == 10 } Some ( Some ( 10 )) flatMap { _ map { _ + 10 }} var newValue1 = 0 Some ( 20 ) foreach { newValue1 = _ } flatMap of Options will filter out all Nones and keep the Somes val list = List ( 1 , 2 , 3 , 4 , 5 ) val result = list . flatMap ( it => if ( it % 2 == 0 ) Some ( it ) else None ) Using \"for comprehension\" val values = List ( Some ( 10 ), Some ( 20 ), None , Some ( 15 )) val newValues = for { someValue <- values value <- someValue } yield value","title":"Option[T]"},{"location":"Scala/Scala_Collections/#java-interop","text":"Scala can implicitly convert from a Scala collection type into a Java collection type. import scala.collection.JavaConversions._","title":"Java Interop"},{"location":"Scala/Scala_Database_Access/","text":"Database Access / ORM Libraries \u00b6 Slick Manual JOOQ Squeryl SORM Doobie ReactiveMongo Comparison of multiple frameworks Database Initialization / Migration \u00b6 Flyway","title":"Scala Database Access"},{"location":"Scala/Scala_Database_Access/#database-access--orm-libraries","text":"Slick Manual JOOQ Squeryl SORM Doobie ReactiveMongo Comparison of multiple frameworks","title":"Database Access / ORM Libraries"},{"location":"Scala/Scala_Database_Access/#database-initialization--migration","text":"Flyway","title":"Database Initialization / Migration"},{"location":"Scala/Scala_Design_Patterns/","text":"Create a new project from template \u00b6 Use the \u201csbt new\u201d command, providing the name of the template. For example, \u201c$ sbt new akka/hello-akka.g8\u201d. You can find a list of templates here . Or download from Scala Project Templates Static Factory \u00b6 trait Animal class Bird extends Animal class Mammal extends Animal class Fish extends Animal object Animal { def apply ( animal : String ) : Animal = animal . toLowerCase match { case \"bird\" => new Bird case \"mammal\" => new Mammal case \"fish\" => new Fish case x : String => throw new RuntimeException ( s\"Unknown animal: $x \" ) } } Algebraic Data Types and Pattern Matching \u00b6 Goal: translate data descriptions into code Model data with logical ors and logical ands Two patterns: product types (and) sum types (or) Product type: A has a B and C Sum type: A is a B or C Sum and product together make algebraic data types // A has a B and C case class A ( b : B , c : C ) // A is a B or C sealed trait A case class B () extends A case class C () extends A They have only data and do not contain any functionality on top of this data as normal classes would. sealed trait Shape case class Circle ( radius : Double ) extends Shape case class Rectangle ( height : Double , width : Double ) extends Shape object Shape { def area ( shape : Shape ) : Double = shape match { case Circle ( Point ( x , y ), radius ) => Math . PI * Math . pow ( radius , 2 ) // use pattern matching to process case Rectangle ( _ , h , w ) => h * w } } Stackable Traits \u00b6 abstract class StringWriter { def write ( data : String ) : String } class BasicStringWriter extends StringWriter { override def write ( data : String ) : String = s\"Writing the following data: ${ data } \" } trait CapitalizingStringWriter extends StringWriter { abstract override def write ( data : String ) : String = { super . write ( data . split ( \"\\\\s+\" ). map ( _ . capitalize ). mkString ( \" \" )) } } trait UppercasingStringWriter extends StringWriter { abstract override def write ( data : String ) : String = { super . write ( data . toUpperCase ) } } object Example { def main ( args : Array [ String ]) : Unit = { val writer1 = new BasicStringWriter with UppercasingStringWriter with CapitalizingStringWriter System . out . println ( s\"Writer 1: ' ${ writer1 . write ( \"we like learning scala!\" ) } '\" ) } } Stackable traits order of execution Stackable traits are always executed from the right mixin to the left. Sometimes, however, if we only get output and it doesn't depend on what is passed to the method, we simply end up with method calls on a stack, which then get evaluated and it will appear as if things are applied from left to right. Components / Cake Pattern \u00b6 http://jonasboner.com/real-world-scala-dependency-injection-di/ // Service Interfaces and Component Definitions trait OnOffDeviceComponent { val onOff : OnOffDevice // abstract val trait OnOffDevice { def on: Unit def off: Unit } } trait SensorDeviceComponent { val sensor : SensorDevice trait SensorDevice { def isCoffeePresent : Boolean } } // ======================= // Component / Service Implementations trait OnOffDeviceComponentImpl extends OnOffDeviceComponent { class Heater extends OnOffDevice { def on = println ( \"heater.on\" ) def off = println ( \"heater.off\" ) } } trait SensorDeviceComponentImpl extends SensorDeviceComponent { class PotSensor extends SensorDevice { def isCoffeePresent = true } } // ======================= // Component declaring two dependencies that it wants injected trait WarmerComponentImpl { this: SensorDeviceComponent with OnOffDeviceComponent => // Use of self-type for composition class Warmer { def trigger = { if ( sensor . isCoffeePresent ) onOff . on else onOff . off } } } // ======================= // Instantiation (and configuration) of the services in the ComponentRegistry module object ComponentRegistry extends OnOffDeviceComponentImpl with SensorDeviceComponentImpl with WarmerComponentImpl { val onOff = new Heater // all instantiations in one spot; can be easily be replaced by e.g. mocks val sensor = new PotSensor val warmer = new Warmer } // ======================= val warmer = ComponentRegistry . warmer warmer . trigger Type Classes (using context-bound type parameters) \u00b6 Ad-hoc polymorphism Break free from your class oppressors! Concerns that cross class hierarchy e.g. serialize to JSON Common behaviour without (useful) common type Abstract behaviour to a type class Can implement type class instances in ad-hoc manner // Define some behavior in terms of operations that a type must support in order to be considered a member of the type class. trait Number [ T ] { def plus ( x : T , y : T ) : T def divide ( x : T , y : Int ) : T } // Define the default type class members in the companion object of the trait object Number { implicit object DoubleNumber extends Number [ Double ] { // note the implicit override def plus ( x : Double , y : Double ) : Double = x + y override def divide ( x : Double , y : Int ) : Double = x / y } } object Stats { // older pattern with implicit parameter // def mean[T](xs: Vector[T])(implicit ev: Number[T]): T = // note the implicit // ev.divide(xs.reduce(ev.plus(_, _)), xs.size) def mean [ T: Number ]( xs : Vector [ T ]) : T = // note the context bound implicitly [ Number [ T ]]. divide ( xs . reduce ( implicitly [ Number [ T ]]. plus ( _ , _ )), // retrieve the evidence via implicitly[] xs . size ) } Visitor Pattern \u00b6 abstract class Element ( text : String ) { def accept ( visitor : Visitor ) } case class Title ( text : String ) extends Element ( text ) { override def accept ( visitor : Visitor ) : Unit = { visitor . visit ( this ) } } case class Text ( text : String ) extends Element ( text ) { override def accept ( visitor : Visitor ) : Unit = { visitor . visit ( this ) } } class Document ( parts : List [ Element ]) { def accept ( visitor : Visitor ) : Unit = { parts . foreach ( p => p . accept ( visitor )) } } trait Visitor { def visit ( element : Element ) } class VisitorImpl1 extends Visitor { override def visit ( element : Element ) : Unit = { element match { case Title ( text ) => ??? case Text ( text ) => ??? //... } } } Configuration \u00b6 import com.typesafe.config.ConfigFactory trait AppConfigComponent { val appConfigService : AppConfigService class AppConfigService () { //-Dconfig.resource=production.conf for overriding private val conf = ConfigFactory . load () private val appConf = conf . getConfig ( \"job-scheduler\" ) private val db = appConf . getConfig ( \"db\" ) val configPath = appConf . getString ( \"config-path\" ) val configExtension = appConf . getString ( \"config-extension\" ) val workers = appConf . getInt ( \"workers\" ) val dbConnectionString = db . getString ( \"connection-string\" ) val dbUsername = db . getString ( \"username\" ) val dbPassword = db . getString ( \"password\" ) } } Memoization \u00b6 import scala.collection.mutable.Map trait Memoizer { def memo [ X , Y ]( f : X => Y ) : ( X => Y ) = { val cache = Map [ X , Y ]() ( x : X ) => cache . getOrElseUpdate ( x , f ( x )) } } Using scalaz: val memoScalaz : String => String = Memo . mutableHashMapMemo { func } Pimp my Library Pattern \u00b6 The pimp my library design pattern is really similar to extension methods in C#. package object pimp { implicit class StringExtensions ( val s : String ) extends AnyVal { def isAllUpperCase : Boolean = ( 0 to s . size - 1 ). find { case index => ! s . charAt ( index ). isUpper }. isEmpty } }","title":"Scala Design Patterns"},{"location":"Scala/Scala_Design_Patterns/#create-a-new-project-from-template","text":"Use the \u201csbt new\u201d command, providing the name of the template. For example, \u201c$ sbt new akka/hello-akka.g8\u201d. You can find a list of templates here . Or download from Scala Project Templates","title":"Create a new project from template"},{"location":"Scala/Scala_Design_Patterns/#static-factory","text":"trait Animal class Bird extends Animal class Mammal extends Animal class Fish extends Animal object Animal { def apply ( animal : String ) : Animal = animal . toLowerCase match { case \"bird\" => new Bird case \"mammal\" => new Mammal case \"fish\" => new Fish case x : String => throw new RuntimeException ( s\"Unknown animal: $x \" ) } }","title":"Static Factory"},{"location":"Scala/Scala_Design_Patterns/#algebraic-data-types-and-pattern-matching","text":"Goal: translate data descriptions into code Model data with logical ors and logical ands Two patterns: product types (and) sum types (or) Product type: A has a B and C Sum type: A is a B or C Sum and product together make algebraic data types // A has a B and C case class A ( b : B , c : C ) // A is a B or C sealed trait A case class B () extends A case class C () extends A They have only data and do not contain any functionality on top of this data as normal classes would. sealed trait Shape case class Circle ( radius : Double ) extends Shape case class Rectangle ( height : Double , width : Double ) extends Shape object Shape { def area ( shape : Shape ) : Double = shape match { case Circle ( Point ( x , y ), radius ) => Math . PI * Math . pow ( radius , 2 ) // use pattern matching to process case Rectangle ( _ , h , w ) => h * w } }","title":"Algebraic Data Types and Pattern Matching"},{"location":"Scala/Scala_Design_Patterns/#stackable-traits","text":"abstract class StringWriter { def write ( data : String ) : String } class BasicStringWriter extends StringWriter { override def write ( data : String ) : String = s\"Writing the following data: ${ data } \" } trait CapitalizingStringWriter extends StringWriter { abstract override def write ( data : String ) : String = { super . write ( data . split ( \"\\\\s+\" ). map ( _ . capitalize ). mkString ( \" \" )) } } trait UppercasingStringWriter extends StringWriter { abstract override def write ( data : String ) : String = { super . write ( data . toUpperCase ) } } object Example { def main ( args : Array [ String ]) : Unit = { val writer1 = new BasicStringWriter with UppercasingStringWriter with CapitalizingStringWriter System . out . println ( s\"Writer 1: ' ${ writer1 . write ( \"we like learning scala!\" ) } '\" ) } } Stackable traits order of execution Stackable traits are always executed from the right mixin to the left. Sometimes, however, if we only get output and it doesn't depend on what is passed to the method, we simply end up with method calls on a stack, which then get evaluated and it will appear as if things are applied from left to right.","title":"Stackable Traits"},{"location":"Scala/Scala_Design_Patterns/#components--cake-pattern","text":"http://jonasboner.com/real-world-scala-dependency-injection-di/ // Service Interfaces and Component Definitions trait OnOffDeviceComponent { val onOff : OnOffDevice // abstract val trait OnOffDevice { def on: Unit def off: Unit } } trait SensorDeviceComponent { val sensor : SensorDevice trait SensorDevice { def isCoffeePresent : Boolean } } // ======================= // Component / Service Implementations trait OnOffDeviceComponentImpl extends OnOffDeviceComponent { class Heater extends OnOffDevice { def on = println ( \"heater.on\" ) def off = println ( \"heater.off\" ) } } trait SensorDeviceComponentImpl extends SensorDeviceComponent { class PotSensor extends SensorDevice { def isCoffeePresent = true } } // ======================= // Component declaring two dependencies that it wants injected trait WarmerComponentImpl { this: SensorDeviceComponent with OnOffDeviceComponent => // Use of self-type for composition class Warmer { def trigger = { if ( sensor . isCoffeePresent ) onOff . on else onOff . off } } } // ======================= // Instantiation (and configuration) of the services in the ComponentRegistry module object ComponentRegistry extends OnOffDeviceComponentImpl with SensorDeviceComponentImpl with WarmerComponentImpl { val onOff = new Heater // all instantiations in one spot; can be easily be replaced by e.g. mocks val sensor = new PotSensor val warmer = new Warmer } // ======================= val warmer = ComponentRegistry . warmer warmer . trigger","title":"Components / Cake Pattern"},{"location":"Scala/Scala_Design_Patterns/#type-classes-using-context-bound-type-parameters","text":"Ad-hoc polymorphism Break free from your class oppressors! Concerns that cross class hierarchy e.g. serialize to JSON Common behaviour without (useful) common type Abstract behaviour to a type class Can implement type class instances in ad-hoc manner // Define some behavior in terms of operations that a type must support in order to be considered a member of the type class. trait Number [ T ] { def plus ( x : T , y : T ) : T def divide ( x : T , y : Int ) : T } // Define the default type class members in the companion object of the trait object Number { implicit object DoubleNumber extends Number [ Double ] { // note the implicit override def plus ( x : Double , y : Double ) : Double = x + y override def divide ( x : Double , y : Int ) : Double = x / y } } object Stats { // older pattern with implicit parameter // def mean[T](xs: Vector[T])(implicit ev: Number[T]): T = // note the implicit // ev.divide(xs.reduce(ev.plus(_, _)), xs.size) def mean [ T: Number ]( xs : Vector [ T ]) : T = // note the context bound implicitly [ Number [ T ]]. divide ( xs . reduce ( implicitly [ Number [ T ]]. plus ( _ , _ )), // retrieve the evidence via implicitly[] xs . size ) }","title":"Type Classes (using context-bound type parameters)"},{"location":"Scala/Scala_Design_Patterns/#visitor-pattern","text":"abstract class Element ( text : String ) { def accept ( visitor : Visitor ) } case class Title ( text : String ) extends Element ( text ) { override def accept ( visitor : Visitor ) : Unit = { visitor . visit ( this ) } } case class Text ( text : String ) extends Element ( text ) { override def accept ( visitor : Visitor ) : Unit = { visitor . visit ( this ) } } class Document ( parts : List [ Element ]) { def accept ( visitor : Visitor ) : Unit = { parts . foreach ( p => p . accept ( visitor )) } } trait Visitor { def visit ( element : Element ) } class VisitorImpl1 extends Visitor { override def visit ( element : Element ) : Unit = { element match { case Title ( text ) => ??? case Text ( text ) => ??? //... } } }","title":"Visitor Pattern"},{"location":"Scala/Scala_Design_Patterns/#configuration","text":"import com.typesafe.config.ConfigFactory trait AppConfigComponent { val appConfigService : AppConfigService class AppConfigService () { //-Dconfig.resource=production.conf for overriding private val conf = ConfigFactory . load () private val appConf = conf . getConfig ( \"job-scheduler\" ) private val db = appConf . getConfig ( \"db\" ) val configPath = appConf . getString ( \"config-path\" ) val configExtension = appConf . getString ( \"config-extension\" ) val workers = appConf . getInt ( \"workers\" ) val dbConnectionString = db . getString ( \"connection-string\" ) val dbUsername = db . getString ( \"username\" ) val dbPassword = db . getString ( \"password\" ) } }","title":"Configuration"},{"location":"Scala/Scala_Design_Patterns/#memoization","text":"import scala.collection.mutable.Map trait Memoizer { def memo [ X , Y ]( f : X => Y ) : ( X => Y ) = { val cache = Map [ X , Y ]() ( x : X ) => cache . getOrElseUpdate ( x , f ( x )) } } Using scalaz: val memoScalaz : String => String = Memo . mutableHashMapMemo { func }","title":"Memoization"},{"location":"Scala/Scala_Design_Patterns/#pimp-my-library-pattern","text":"The pimp my library design pattern is really similar to extension methods in C#. package object pimp { implicit class StringExtensions ( val s : String ) extends AnyVal { def isAllUpperCase : Boolean = ( 0 to s . size - 1 ). find { case index => ! s . charAt ( index ). isUpper }. isEmpty } }","title":"Pimp my Library Pattern"},{"location":"Scala/Scala_Generalities/","text":"Main Features of Scala \u00b6 All types are objects Type inference Nested Functions Functions are objects Domain specific language (DSL) support Traits Closures Concurrency support inspired by Erlang Tools and Frameworks \u00b6 REPL http://ammonite.io/ https://scalafiddle.io/ The Lift Framework The Play framework The Bowler framework Akka https://typelevel.org/ Install \u00b6 Need to have Java Software Development Kit (SDK) installed java -version export JAVA_HOME = /usr/local/java-current export PATH = $PATH : $JAVA_HOME /bin/ http://www.scala-lang.org/download/ Compilation \u00b6 scalac HelloWorld.scala // produces HelloWorld.class scala -classpath . HelloWorld","title":"Scala (Generalities)"},{"location":"Scala/Scala_Generalities/#main-features-of-scala","text":"All types are objects Type inference Nested Functions Functions are objects Domain specific language (DSL) support Traits Closures Concurrency support inspired by Erlang","title":"Main Features of Scala"},{"location":"Scala/Scala_Generalities/#tools-and-frameworks","text":"REPL http://ammonite.io/ https://scalafiddle.io/ The Lift Framework The Play framework The Bowler framework Akka https://typelevel.org/","title":"Tools and Frameworks"},{"location":"Scala/Scala_Generalities/#install","text":"Need to have Java Software Development Kit (SDK) installed java -version export JAVA_HOME = /usr/local/java-current export PATH = $PATH : $JAVA_HOME /bin/ http://www.scala-lang.org/download/","title":"Install"},{"location":"Scala/Scala_Generalities/#compilation","text":"scalac HelloWorld.scala // produces HelloWorld.class scala -classpath . HelloWorld","title":"Compilation"},{"location":"Scala/Scala_Language/","text":"Links \u00b6 Scala Cheatsheet Scala @ TutorialPoint Scala Tutorial (PDF) Some examples are derived from Scala Koans . Basics \u00b6 Style \u00b6 Class Names - For all class names, the first letter should be in Upper Case. If several words are used to form a name of the class, each inner word's first letter should be in Upper Case. class MyFirstScalaClass Method Names - All method names should start with a Lower Case letter. If multiple words are used to form the name of the method, then each inner word's first letter should be in Upper Case. def myMethodName() Program File Name - Name of the program file should exactly match the object name. When saving the file you should save it using the object name (Remember Scala is case-sensitive) and append \".scala\" to the end of the name. If the file name and the object name do not match your program will not compile. Assume 'HelloWorld' is the object name: the file should be saved as 'HelloWorld.scala'. Packages \u00b6 package pkg // at start of file package pkg { ... } // bracket style Imports \u00b6 import scala.collection._ // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*). import scala.collection.Vector // one class import import scala.collection. { Vector , Sequence } // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces import scala.collection. { Vector => Vec28 } // renaming import. import java.util. { Date => _ , _ } // import all from java.util except Date. All classes from the java.lang package are imported by default. The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification: - immutable Map, Set, List, ::, Nil, print, println, assert, assume, require, ensuring import scala.collection.mutable.HashMap // Mutable collections must be imported. import scala.collection.immutable. { TreeMap , TreeSet } // So are specialized collections. Application Entry Point \u00b6 object HelloWorld { def main ( args : Array [ String ]) { println ( \"Hello, world!\" ) } } Blocks \u00b6 You can combine expressions by surrounding them with {}. We call this a block. The result of the last expression in the block is the result of the overall block, too. println ({ val x = 1 + 1 x + 1 }) // 3 Variables and Values \u00b6 var x = 5 // variable val x = 5 // immutable value / \"const\" var x : Double = 5 // explicit type println ( x ) A lazy val is assignment that will not evaluated until it is called. Note there is no lazy var lazy val a = { heavymath (); 19 } Literals \u00b6 val a = 2 // int val b = 31L // long val c = 0x30B // hexadecimal val d = 3 f // float val e = 3.22d // double val f = 93 e - 9 val g = 'a' // character val h = '\\u0061' // unicode for a val i = ' \\ 141 ' // octal for a val j = '\\\"' // escape sequences val k = '\\\\' val s = \"To be or not to be\" // string s . charAt ( 0 ) val s2 = \"\"\"An apple a day keeps the doctor away\"\"\" // multi-lines string s2 . split ( '\\n' ) val s3 = \"\"\"An apple a day |keeps the doctor away\"\"\" // Multiline String literals can use | to specify the starting position of subsequent lines, then use stripMargin to remove the surplus indentation. s3 . stripMargin Enumerations \u00b6 object Planets extends Enumeration { val Mercury = Value val Venus = Value val Earth = Value val Mars = Value val Jupiter = Value val Saturn = Value val Uranus = Value val Neptune = Value val Pluto = Value } Planets . Mercury . id Planets . Mercury . toString //How does it get the name? by Reflection. object GreekPlanets extends Enumeration { val Mercury = Value ( 1 , \"Hermes\" ) // enumeration with your own index and/or your own Strings val Venus = Value ( 2 , \"Aphrodite\" ) //Fun Fact: Tellus is Roman for (Mother) Earth val Earth = Value ( 3 , \"Gaia\" ) val Mars = Value ( 4 , \"Ares\" ) val Jupiter = Value ( 5 , \"Zeus\" ) val Saturn = Value ( 6 , \"Cronus\" ) val Uranus = Value ( 7 , \"Ouranus\" ) val Neptune = Value ( 8 , \"Poseidon\" ) val Pluto = Value ( 9 , \"Hades\" ) } Common Data Structures \u00b6 ( 1 , 2 , 3 ) // tuple literal. (Tuple3) var ( x , y , z ) = ( 1 , 2 , 3 ) // destructuring bind: tuple unpacking via pattern matching. // BAD var x,y,z = (1,2,3) // hidden error: each assigned to the entire tuple. val tuple = ( \"apple\" , 3 ) // mixed type tuple tuple . _1 tuple . _2 tuple . swap var xs = List ( 1 , 2 , 3 ) // list (immutable). xs ( 2 ) // paren indexing 1 :: List ( 2 , 3 ) // cons (create a new list by prepending the element). 1 to 5 // Range sugar. Same as `1 until 6` 1 to 10 by 2 Range ( 1 , 10 , 2 ) // Range does not include the last item, even in a step increment Range ( 1 , 9 , 2 ). inclusive () // (empty parens) sole member of the Unit type (like C/Java void). Control Constructs \u00b6 if ( check ) happy else sad // conditional. if ( check ) happy // if ( check ) happy else () // same as above while ( x < 5 ) { println ( x ); x += 1 } // while loop. do { println ( x ); x += 1 } while ( x < 5 ) // do while loop. for ( x <- xs if x % 2 == 0 ) yield x * 10 // for comprehension with guard xs . filter ( _ % 2 == 0 ). map ( _ * 10 ) // same as filter/map for (( x , y ) <- xs zip ys ) yield x * y // for comprehension: destructuring bind ( xs zip ys ) map { case ( x , y ) => x * y } // same as for ( x <- xs ; y <- ys ) yield x * y // for comprehension: cross product. Later generators varying more rapidly than earlier ones xs flatMap { x => ys map { y => x * y }} // same as for ( x <- xs ; y <- ys ) { println ( \"%d/%d = %.1f\" . format ( x , y , x / y . toFloat )) // for comprehension: imperative-ish } for ( i <- 1 to 5 ) { // for comprehension: iterate including the upper bound println ( i ) } for ( i <- 1 until 5 ) { // for comprehension: iterate omitting the upper bound println ( i ) } import scala.util.control.Breaks._ // break breakable { for ( x <- xs ) { if ( Math . random < 0.1 ) break } } Formatting and Interpolation \u00b6 val helloMessage = \"Hello World\" s\"Application $helloMessage \" // string interpolation; can include expressions which can include numbers and strings // use `f` prefix before the string instead of an `s` for sprintf formatting Functions \u00b6 Scala is a functional language in the sense that every function is a value and every value is an object so ultimately every function is an object. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. def add ( x : Int , y : Int ) : Int = x + y // the return type is declared after the parameter list and a colon // GOOD def f(x: Any) = println(x) // BAD def f(x) = println(x) // syntax error: need types for every arg. def f ( x : Int ) = { // inferred return type val square = x * x square . toString } // The last expression in the body is the method\u2019s return value. (Scala does have a return keyword, but it\u2019s rarely used.) // BAD def f(x: Int) { x*x } hidden error: without = it\u2019s a Unit-returning procedure; causes havoc // When performing recursion, the return type on the method is mandatory! Backticks for reserved keywords and identifiers with a space (rare) def `put employee on probation` ( employee : Employee ) = { new Employee ( employee . `first name` , employee . `last name` , \"Probation\" ) } Multiple parameter lists or none at all \u00b6 def addThenMultiply ( x : Int , y : Int )( multiplier : Int ) : Int = ( x + y ) * multiplier def name : String = System . getProperty ( \"name\" ) Procedures \u00b6 def foo ( x : Int ) { //Note: No `=`; returns Unit print ( x . toString ) } def foo ( x : Int ) : Unit = print ( x . toString ) // or Convention (not required for the compiler) states that if you a call a method that returns a Unit / has a side effect, invoke that method with empty parenthesis, other leave the parenthesis out def performSideEffect () : Unit = System . currentTimeMillis performSideEffect () Default and named parameters \u00b6 def addColorsWithDefaults ( red : Int = 0 , green : Int = 0 , blue : Int = 0 ) = { ( red , green , blue ) } me . addColors ( blue = 40 ) Variable Length Arguments \u00b6 def sum ( args : Int* ) = args . reduceLeft ( _ + _ ) // varargs. must be last arg def capitalizeAll ( args : String* ) = { args . map { arg => arg . capitalize } } capitalizeAll ( \"rarity\" , \"applejack\" ) If you want a collection expanded into a vararg, add :_* def repeatedParameterMethod ( x : Int , y : String , z : Any* ) = { \"%d %ss can give you %s\" . format ( x , y , z . mkString ( \", \" )) } repeatedParameterMethod ( 3 , \"egg\" , List ( \"a delicious sandwich\" , \"protein\" , \"high cholesterol\" ) :_ * ) should be ( __ ) Tail recursion \u00b6 As a precaution, the helpful @tailrec annotation will throw a compile time if a method is not tail recursive, meaning that the last call and only call of the method is the recursive method. Scala optimizes recursive calls to a loop from a stack import scala.annotation.tailrec // importing annotation! @tailrec // compiler will check that the function is tail recursive def factorial ( i : BigInt ) : BigInt = { @tailrec def fact ( i : BigInt , accumulator : BigInt ) : BigInt = { // methods can be placed inside in methods; return type is obligatory if ( i <= 1 ) accumulator else fact ( i - 1 , i * accumulator ) } fact ( i , 1 ) } factorial ( 3 ) Infix, Postfix and Prefix Notations; Operators \u00b6 object FrenchDate { def main ( args : Array [ String ]) { val now = new Date val df = getDateInstance ( LONG , Locale . FRANCE ) println ( df format now ) // Methods taking one argument can be used with an infix syntax. Equivalent to df.format(now) } } 1 + 2 * 3 / x consists exclusively of method calls, because it is equivalent to the following expression: (1).+(((2).*(3))./(x)) This also means that +, *, etc. are valid identifiers in Scala. Infix Operators do NOT work if an object has a method that takes two parameters. val g : Int = 31 val s : String = g toHexString // Postfix operators work if an object has a method that takes no parameters Prefix operators work if an object has a method name that starts with unary_ class Stereo { def unary_+ = \"on\" def unary_- = \"off\" } val stereo = new Stereo + stereo // it is on Methods with colons are right-associative, that means the object that a method is on will be on the right and the method parameter will be on the left class Foo ( y : Int ) { def ~:( n : Int ) = n + y + 3 } val foo = new Foo ( 9 ) 10 ~: foo foo .~:( 10 ) // same as Anonymous Functions \u00b6 def lambda = ( x : Int ) => x + 1 // other variants def lambda2 = { x : Int => x + 1 } val lambda3 = new Function1 [ Int , Int ] { def apply ( v1 : Int ) : Int = v1 + 1 } val everything = () => 42 // without parameter val add = ( x : Int , y : Int ) => x + y // multiple parameters ( 1 to 5 ). map ( _ * 2 ) // underscore notation. ( 1 to 5 ) map ( _ * 2 ) // same with infix sugar. ( 1 to 5 ). reduceLeft ( _ + _ ) // underscores are positionally matched 1st and 2nd args. ( 1 to 5 ). map ( x => x * x ) // to use an arg twice, have to name it. ( 1 to 5 ). map { x => val y = x * 2 ; println ( y ); y } // block style returns last expression. ( 1 to 5 ) filter { _ % 2 == 0 } map { _ * 2 } // pipeline style (works with parens too). // GOOD (1 to 5).map(2*) // BAD (1 to 5).map(*2) // anonymous function: bound infix method. Use 2*_ for sanity\u2019s sake instead. def compose ( g : R => R , h : R => R ) = ( x : R ) => g ( h ( x )) val f = compose ({ _ * 2 }, { _ - 1 }) // anonymous functions: to pass in multiple blocks, need outer parens. Passing anonymous functions as parameter: def makeWhatEverYouLike ( xs : List [ String ], func : String => String ) = { xs map func } Function returning another function using an anonymous function: def add ( x : Int ) = ( y : Int ) => x + y Function Values: object Timer { def oncePerSecond ( callback : () => Unit ) { // () => T is a Function type that takes a Unit type. Unit is known as 'void' to a Java programmer. while ( true ) { callback (); Thread sleep 1000 } } def timeFlies () { println ( \"time flies like an arrow...\" ) } def main ( args : Array [ String ]) { oncePerSecond ( timeFlies ) // function value; could also be () => timeFlies() } } By-name parameter \u00b6 This is used extensively in scala to create blocks. def calc ( x : => Int ) : Either [ Throwable , Int ] = { //x is a call by name parameter; delayed execution of x try { Right ( x ) } catch { case b : Throwable => Left ( b ) } } val y = calc { //This looks like a natural block println ( \"Here we go!\" ) //Some superfluous call 49 + 20 } By name parameters can also be used with an Object and apply to make interesting block-like calls object PigLatinizer { def apply ( x : => String ) = x . tail + x . head + \"ay\" } val result = PigLatinizer { val x = \"pret\" val z = \"zel\" x ++ z //concatenate the strings } Closures \u00b6 var incrementer = 1 def closure = { x : Int => x + incrementer } Currying \u00b6 val zscore = ( mean : R , sd : R ) => ( x : R ) => ( x - mean )/ sd // currying, obvious syntax. def zscore ( mean : R , sd : R ) = ( x : R ) => ( x - mean )/ sd // currying, obvious syntax def zscore ( mean : R , sd : R )( x : R ) = ( x - mean )/ sd // currying, sugar syntax. but then: val normer = zscore ( 7 , 0.4 ) _ // need trailing underscore to get the partial, only for the sugar version. def mapmake [ T ]( g : T => T )( seq : List [ T ]) = seq . map ( g ) // generic type. def multiply ( x : Int , y : Int ) = x * y val multiplyCurried = ( multiply _ ). curried multiply ( 4 , 5 ) multiplyCurried ( 3 )( 2 ) Partial Applications \u00b6 def adder ( m : Int , n : Int ) = m + n val add2 = adder ( 2 , _: Int ) // You can partially apply any argument in the argument list, not just the last one. add2 ( 3 ) // which is 5 val add3 = adder _ // underscore to convert from a function to a lambda adder ( 1 , 9 ) add3 ( 1 , 9 ) Partial Functions \u00b6 val doubleEvens : PartialFunction [ Int , Int ] = new PartialFunction [ Int , Int ] { // full declaration //States that this partial function will take on the task def isDefinedAt ( x : Int ) = x % 2 == 0 //What we do if this does partial function matches def apply ( v1 : Int ) = v1 * 2 } val tripleOdds : PartialFunction [ Int , Int ] = { case x : Int if ( x % 2 ) != 0 => x * 3 // syntaxic sugar (usual way) } val whatToDo = doubleEvens orElse tripleOdds // combine the partial functions together: OrElse val addFive = ( x : Int ) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive // chain (partial) functions together: andThen Classes, Objects, and Traits \u00b6 class C ( x : R ) // constructor params - x is only available in class body class C ( val x : R ) // c.x constructor params - automatic public (immutable) member defined class D ( var x : R ) // you can define class with var or val parameters class C ( var x : R ) { assert ( x > 0 , \"positive please\" ) // constructor is class body var y = x // declare a public member val readonly = 5 // declare a gettable but not settable member private var secret = 1 // declare a private member def this = this ( 42 ) // alternative constructor } new { ... } // anonymous class abstract class D { ... } // define an abstract(non-createable) class. class C extends D { ... } // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class class C ( x : R ) extends D ( x ) // inheritance and constructor params. (wishlist: automatically pass-up params by default) // A class can be placed inside another class object O extends D { ... } // define a singleton. trait T { ... } // traits. See below. class C extends T { ... } class C extends D with T { ... } // interfaces-with-implementation. no constructor params. mixin-able. trait T1 ; trait T2 class C extends T1 with T2 // multiple traits. class C extends D with T1 with T2 // parent class and (multiple) trait(s). class C extends D { override def f = ...} // must declare method overrides. var c = new C ( 4 ) // Instantiation //BAD new List[Int] //GOOD List(1,2,3) // Instead, convention: callable factory shadowing the type classOf [ String ] // class literal. classOf [ String ]. getCanonicalName classOf [ String ]. getSimpleName val zoom = \"zoom\" zoom . getClass == classOf [ String ] x . isInstanceOf [ String ] // type check (runtime) x . asInstanceOf [ String ] // type cast (runtime) x : String // compare to parameter ascription (compile time) Methods \u00b6 class Complex ( real : Double , imaginary : Double ) { def re = real // return type inferred automatically by the compiler def im = imaginary // methods without arguments def print () : Unit = println ( s\" $real + i * $imaginary \" ) override def toString () = \"\" + re + ( if ( im < 0 ) \"\" else \"+\" ) + im + \"i\" // override methods inherited from a super-class } Asserts and Contracts \u00b6 Asserts take a boolean argument and can take a message. assert ( true ) // should be true assert ( true , \"This should be true\" ) def addNaturals ( nats : List [ Int ]) : Int = { require ( nats forall ( _ >= 0 ), \"List contains negative numbers\" ) nats . foldLeft ( 0 )( _ + _ ) } ensuring ( _ >= 0 ) Path-dependent Classes \u00b6 When a class is instantiated inside of another object, it belongs to the instance. This is a path dependent type. Once established, it cannot be placed inside of another object case class Board ( length : Int , height : Int ) { case class Coordinate ( x : Int , y : Int ) } val b1 = Board ( 20 , 20 ) val b2 = Board ( 30 , 30 ) val c1 = b1 . Coordinate ( 15 , 15 ) val c2 = b2 . Coordinate ( 25 , 25 ) // val c1 = c2 won't work Use A#B for a Java-style inner class: class Graph { class Node { var connectedNodes : List [ Graph # Node ] = Nil // accepts Nodes from any Graph def connectTo ( node : Graph # Node ) { if ( connectedNodes . find ( node . equals ). isEmpty ) { connectedNodes = node :: connectedNodes } } } var nodes : List [ Node ] = Nil def newNode : Node = { val res = new Node nodes = res :: nodes res } } Companion Objects \u00b6 Static members (methods or fields) do not exist in Scala. Rather than defining static members, the Scala programmer declares these members in singleton objects, that is a class with a single instance. object TimerAnonymous { def oncePerSecond ( callback : () => Unit ) { while ( true ) { callback (); Thread sleep 1000 } } def main ( args : Array [ String ]) { oncePerSecond (() => println ( \"time flies like an arrow...\" )) } } An object that has the same name as class is called a companion object, it is used to contain factories for the class that it complements. A companion object can also store shared variables and values for every instantiated class to share. A companion object can see private values and variables of the instantiated object Apply Method \u00b6 The apply method is a magical method in Scala. class Employee ( val firstName : String , val lastName : String ) object Employee { def apply ( firstName : String , lastName : String ) = new Employee ( firstName , lastName ) // would also work in a class, but rarer } val a = Employee ( \"John\" , \"Doe\" ) // is equivalent to var b = Employee . apply ( \"John\" , \"Doe\" ) Case Classes \u00b6 The new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)), Getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v), Default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity, A default definition for method toString is provided, and prints the value in a source form (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))), Instances of these classes can be decomposed through pattern matching case class Person ( first : String , last : String , age : Int = 0 ) // Case classes can have default and named parameters val p1 = Person ( \"Fred\" , \"Jones\" ) // new is optional val p2 = new Person ( \"Fred\" , \"Jones\" ) p1 == p2 // true p1 . hashCode == p2 . hashCode // true p1 eq p2 // false val p3 = p2 . copy ( first = \"Jane\" ) // copy the case class but change the name in the copy case class Dog ( var name : String , breed : String ) // Case classes can have mutable properties - potentially unsafe Case classes can be disassembled to their constituent parts as a tuple: val parts = Person . unapply ( p1 ). get // returns Option[T] parts . _1 parts . _2 Algebraic data type \u00b6 sealed trait Tree // or abstract class final case class Sum ( l : Tree , r : Tree ) extends Tree final case class Var ( n : String ) extends Tree final case class Const ( v : Int ) extends Tree Pattern Matching \u00b6 { case \"x\" => 5 } defines a partial function which, when given the string \"x\" as argument, returns the integer 5, and fails with an exception otherwise. type Environment = String => Int // the type Environment can be used as an alias of the type of functions from String to Int def eval ( t : Tree , env : Environment ) : Int = t match { case Sum ( l , r ) => eval ( l , env ) + eval ( r , env ) case Var ( n ) => env ( n ) case Const ( v ) => v } def derive ( t : Tree , v : String ) : Tree = t match { case Sum ( l , r ) => Sum ( derive ( l , v ), derive ( r , v )) case Var ( n ) if ( v == n ) => Const ( 1 ) // guard, an expression following the if keyword. case _ => Const ( 0 ) // wild-card, written _, which is a pattern matching any value, without giving it a name. } // GOOD (xs zip ys) map { case (x,y) => x*y } // BAD (xs zip ys) map( (x,y) => x*y ) // use case in function args for pattern matching. // BAD val v42 = 42 Some ( 3 ) match { case Some ( v42 ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // \u201cv42\u201d is interpreted as a name matching any Int value, and \u201c42\u201d is printed. // GOOD val v42 = 42 Some ( 3 ) match { case Some ( `v42` ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // \u201d`v42`\u201d with backticks is interpreted as the existing val v42, and \u201cNot 42\u201d is printed. // GOOD val UppercaseVal = 42 Some ( 3 ) match { case Some ( UppercaseVal ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter. // Thus, the value contained within UppercaseVal is checked against 3, and \u201cNot 42\u201d is printed. List Matching \u00b6 val secondElement = List ( 1 , 2 , 3 ) match { case x :: y :: xs => xs case x :: Nil => x case _ => 0 } Regex \u00b6 val MyRegularExpression = \"\"\"a=([^,]+),\\s+b=(.+)\"\"\" . r //.r turns a String to a regular expression expr match { case ( MyRegularExpression ( a , b )) => a + b } import scala.util.matching.Regex val numberPattern : Regex = \"[0-9]\" . r numberPattern . findFirstMatchIn ( \"awesomepassword\" ) match { case Some ( _ ) => println ( \"Password OK\" ) case None => println ( \"Password must contain a number\" ) } With groups: val keyValPattern : Regex = \"([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)\" . r for ( patternMatch <- keyValPattern . findAllMatchIn ( input )) println ( s\"key: ${ patternMatch . group ( 1 ) } value: ${ patternMatch . group ( 2 ) } \" ) Extractors (unapply) \u00b6 class Car ( val make : String , val model : String , val year : Short , val topSpeed : Short ) object Car { // What is typical is to create a custom extractor in the companion object of the class. def unapply ( x : Car ) = Some ( x . make , x . model , x . year , x . topSpeed ) // returns an Option[T] } val Car ( a , b , c , d ) = new Car ( \"Chevy\" , \"Camaro\" , 1978 , 120 ) // assign values to a .. d val x = new Car ( \"Chevy\" , \"Camaro\" , 1978 , 120 ) match { // pattern matching case Car ( s , t , _ , _ ) => ( s , t ) // _ for variables we don't care about. case _ => ( \"Ford\" , \"Edsel\" ) // fallback } As long as the method signatures aren't the same, you can have an many unapply methods as you want in the same class / object. When you create a case class, it automatically can be used with pattern matching since it has an extractor. Value Class \u00b6 Avoid allocating runtime objects. class Wrapper ( val underlying : Int ) extends AnyVal { def foo : Wrapper = new Wrapper ( underlying * 19 ) } It has a single, public val parameter that is the underlying runtime representation. The type at compile time is Wrapper, but at runtime, the representation is an Int. A value class can define defs, but no vals, vars, or nested traitss, classes or objects A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation. Traits \u00b6 Apart from inheriting code from a super-class, a Scala class can also import code from one or several traits i.e. interfaces which can also contain code. In Scala, when a class inherits from a trait, it implements that traits's interface, and inherits all the code contained in the trait. trait Ord { def < ( that : Any ) : Boolean // The type Any which is used above is the type which is a super-type of all other types in Scala def <= ( that: Any ) : Boolean = ( this < that ) || ( this == that ) def > ( that : Any ) : Boolean = !( this <= that ) def >=( that : Any ) : Boolean = !( this < that ) } class Date ( y : Int , m : Int , d : Int ) extends Ord { def year = y def month = m def day = d override def toString () : String = year + \"-\" + month + \"-\" + day override def equals ( that : Any ) : Boolean = that . isInstanceOf [ Date ] && { val o = that . asInstanceOf [ Date ] o . day == day && o . month == month && o . year == year } def <( that : Any ) : Boolean = { // The trait declare the type (e.g. method), where a concrete implementer will satisfy the type if (! that . isInstanceOf [ Date ]) error ( \"cannot compare \" + that + \" and a Date\" ) val o = that . asInstanceOf [ Date ]( year < o . year ) || ( year == o . year && ( month < o . month || ( month == o . month && day < o . day ))) } } Traits can have concrete implementations that can be mixed into concrete classes with its own state Traits can be mixed in during instantiation! trait Logging { var logCache = List [ String ]() def log ( value : String ) = { logCache = logCache :+ value } def log = logCache } val a = new A ( \"stuff\" ) with Logging // mixin traits during instantiation! a . log ( \"I did something\" ) a . log . size Stackable Traits \u00b6 abstract class IntQueue { def get () : Int def put ( x : Int ) } import scala.collection.mutable.ArrayBuffer class BasicIntQueue extends IntQueue { private val buf = new ArrayBuffer [ Int ] def get () = buf . remove ( 0 ) def put ( x : Int ) { buf += x } } trait Doubling extends IntQueue { abstract override def put ( x : Int ) { super . put ( 2 * x ) } // abstract override is necessary to stack traits } class MyQueue extends BasicIntQueue with Doubling // could also mixin during instantiation val myQueue = new MyQueue myQueue . put ( 3 ) myQueue . get () More traits can be stacked one atop another, make sure that all overrides are labelled abstract override . The order of the mixins are important. Traits on the right take effect first. Traits are instantiated before a classes instantiation from left to right. Linerization: the diamond inheritance problem is avoided since instantiations are tracked and will not allow multiple instantiations of the same parent trait Classes versus Traits \u00b6 Use classes: When a behavior is not going to be reused at all or in multiple places When you plan to use your Scala code from another language, for example, if you are building a library that could be used in Java Use traits: When a behavior is going to be reused in multiple unrelated classes. When you want to define interfaces and want to use them outside Scala, for example Java. The reason is that the traits that do not have any implementations are compiled similar to interfaces. Keyword List \u00b6 abstract case catch class def do else extends false final finally for forSome if implicit import lazy match new Null object override package private protected return sealed super this throw trait Try true type val var while with yield - : = => <- <: <% >: # @","title":"Scala Language"},{"location":"Scala/Scala_Language/#links","text":"Scala Cheatsheet Scala @ TutorialPoint Scala Tutorial (PDF) Some examples are derived from Scala Koans .","title":"Links"},{"location":"Scala/Scala_Language/#basics","text":"","title":"Basics"},{"location":"Scala/Scala_Language/#style","text":"Class Names - For all class names, the first letter should be in Upper Case. If several words are used to form a name of the class, each inner word's first letter should be in Upper Case. class MyFirstScalaClass Method Names - All method names should start with a Lower Case letter. If multiple words are used to form the name of the method, then each inner word's first letter should be in Upper Case. def myMethodName() Program File Name - Name of the program file should exactly match the object name. When saving the file you should save it using the object name (Remember Scala is case-sensitive) and append \".scala\" to the end of the name. If the file name and the object name do not match your program will not compile. Assume 'HelloWorld' is the object name: the file should be saved as 'HelloWorld.scala'.","title":"Style"},{"location":"Scala/Scala_Language/#packages","text":"package pkg // at start of file package pkg { ... } // bracket style","title":"Packages"},{"location":"Scala/Scala_Language/#imports","text":"import scala.collection._ // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*). import scala.collection.Vector // one class import import scala.collection. { Vector , Sequence } // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces import scala.collection. { Vector => Vec28 } // renaming import. import java.util. { Date => _ , _ } // import all from java.util except Date. All classes from the java.lang package are imported by default. The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification: - immutable Map, Set, List, ::, Nil, print, println, assert, assume, require, ensuring import scala.collection.mutable.HashMap // Mutable collections must be imported. import scala.collection.immutable. { TreeMap , TreeSet } // So are specialized collections.","title":"Imports"},{"location":"Scala/Scala_Language/#application-entry-point","text":"object HelloWorld { def main ( args : Array [ String ]) { println ( \"Hello, world!\" ) } }","title":"Application Entry Point"},{"location":"Scala/Scala_Language/#blocks","text":"You can combine expressions by surrounding them with {}. We call this a block. The result of the last expression in the block is the result of the overall block, too. println ({ val x = 1 + 1 x + 1 }) // 3","title":"Blocks"},{"location":"Scala/Scala_Language/#variables-and-values","text":"var x = 5 // variable val x = 5 // immutable value / \"const\" var x : Double = 5 // explicit type println ( x ) A lazy val is assignment that will not evaluated until it is called. Note there is no lazy var lazy val a = { heavymath (); 19 }","title":"Variables and Values"},{"location":"Scala/Scala_Language/#literals","text":"val a = 2 // int val b = 31L // long val c = 0x30B // hexadecimal val d = 3 f // float val e = 3.22d // double val f = 93 e - 9 val g = 'a' // character val h = '\\u0061' // unicode for a val i = ' \\ 141 ' // octal for a val j = '\\\"' // escape sequences val k = '\\\\' val s = \"To be or not to be\" // string s . charAt ( 0 ) val s2 = \"\"\"An apple a day keeps the doctor away\"\"\" // multi-lines string s2 . split ( '\\n' ) val s3 = \"\"\"An apple a day |keeps the doctor away\"\"\" // Multiline String literals can use | to specify the starting position of subsequent lines, then use stripMargin to remove the surplus indentation. s3 . stripMargin","title":"Literals"},{"location":"Scala/Scala_Language/#enumerations","text":"object Planets extends Enumeration { val Mercury = Value val Venus = Value val Earth = Value val Mars = Value val Jupiter = Value val Saturn = Value val Uranus = Value val Neptune = Value val Pluto = Value } Planets . Mercury . id Planets . Mercury . toString //How does it get the name? by Reflection. object GreekPlanets extends Enumeration { val Mercury = Value ( 1 , \"Hermes\" ) // enumeration with your own index and/or your own Strings val Venus = Value ( 2 , \"Aphrodite\" ) //Fun Fact: Tellus is Roman for (Mother) Earth val Earth = Value ( 3 , \"Gaia\" ) val Mars = Value ( 4 , \"Ares\" ) val Jupiter = Value ( 5 , \"Zeus\" ) val Saturn = Value ( 6 , \"Cronus\" ) val Uranus = Value ( 7 , \"Ouranus\" ) val Neptune = Value ( 8 , \"Poseidon\" ) val Pluto = Value ( 9 , \"Hades\" ) }","title":"Enumerations"},{"location":"Scala/Scala_Language/#common-data-structures","text":"( 1 , 2 , 3 ) // tuple literal. (Tuple3) var ( x , y , z ) = ( 1 , 2 , 3 ) // destructuring bind: tuple unpacking via pattern matching. // BAD var x,y,z = (1,2,3) // hidden error: each assigned to the entire tuple. val tuple = ( \"apple\" , 3 ) // mixed type tuple tuple . _1 tuple . _2 tuple . swap var xs = List ( 1 , 2 , 3 ) // list (immutable). xs ( 2 ) // paren indexing 1 :: List ( 2 , 3 ) // cons (create a new list by prepending the element). 1 to 5 // Range sugar. Same as `1 until 6` 1 to 10 by 2 Range ( 1 , 10 , 2 ) // Range does not include the last item, even in a step increment Range ( 1 , 9 , 2 ). inclusive () // (empty parens) sole member of the Unit type (like C/Java void).","title":"Common Data Structures"},{"location":"Scala/Scala_Language/#control-constructs","text":"if ( check ) happy else sad // conditional. if ( check ) happy // if ( check ) happy else () // same as above while ( x < 5 ) { println ( x ); x += 1 } // while loop. do { println ( x ); x += 1 } while ( x < 5 ) // do while loop. for ( x <- xs if x % 2 == 0 ) yield x * 10 // for comprehension with guard xs . filter ( _ % 2 == 0 ). map ( _ * 10 ) // same as filter/map for (( x , y ) <- xs zip ys ) yield x * y // for comprehension: destructuring bind ( xs zip ys ) map { case ( x , y ) => x * y } // same as for ( x <- xs ; y <- ys ) yield x * y // for comprehension: cross product. Later generators varying more rapidly than earlier ones xs flatMap { x => ys map { y => x * y }} // same as for ( x <- xs ; y <- ys ) { println ( \"%d/%d = %.1f\" . format ( x , y , x / y . toFloat )) // for comprehension: imperative-ish } for ( i <- 1 to 5 ) { // for comprehension: iterate including the upper bound println ( i ) } for ( i <- 1 until 5 ) { // for comprehension: iterate omitting the upper bound println ( i ) } import scala.util.control.Breaks._ // break breakable { for ( x <- xs ) { if ( Math . random < 0.1 ) break } }","title":"Control Constructs"},{"location":"Scala/Scala_Language/#formatting-and-interpolation","text":"val helloMessage = \"Hello World\" s\"Application $helloMessage \" // string interpolation; can include expressions which can include numbers and strings // use `f` prefix before the string instead of an `s` for sprintf formatting","title":"Formatting and Interpolation"},{"location":"Scala/Scala_Language/#functions","text":"Scala is a functional language in the sense that every function is a value and every value is an object so ultimately every function is an object. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. def add ( x : Int , y : Int ) : Int = x + y // the return type is declared after the parameter list and a colon // GOOD def f(x: Any) = println(x) // BAD def f(x) = println(x) // syntax error: need types for every arg. def f ( x : Int ) = { // inferred return type val square = x * x square . toString } // The last expression in the body is the method\u2019s return value. (Scala does have a return keyword, but it\u2019s rarely used.) // BAD def f(x: Int) { x*x } hidden error: without = it\u2019s a Unit-returning procedure; causes havoc // When performing recursion, the return type on the method is mandatory! Backticks for reserved keywords and identifiers with a space (rare) def `put employee on probation` ( employee : Employee ) = { new Employee ( employee . `first name` , employee . `last name` , \"Probation\" ) }","title":"Functions"},{"location":"Scala/Scala_Language/#multiple-parameter-lists-or-none-at-all","text":"def addThenMultiply ( x : Int , y : Int )( multiplier : Int ) : Int = ( x + y ) * multiplier def name : String = System . getProperty ( \"name\" )","title":"Multiple parameter lists or none at all"},{"location":"Scala/Scala_Language/#procedures","text":"def foo ( x : Int ) { //Note: No `=`; returns Unit print ( x . toString ) } def foo ( x : Int ) : Unit = print ( x . toString ) // or Convention (not required for the compiler) states that if you a call a method that returns a Unit / has a side effect, invoke that method with empty parenthesis, other leave the parenthesis out def performSideEffect () : Unit = System . currentTimeMillis performSideEffect ()","title":"Procedures"},{"location":"Scala/Scala_Language/#default-and-named-parameters","text":"def addColorsWithDefaults ( red : Int = 0 , green : Int = 0 , blue : Int = 0 ) = { ( red , green , blue ) } me . addColors ( blue = 40 )","title":"Default and named parameters"},{"location":"Scala/Scala_Language/#variable-length-arguments","text":"def sum ( args : Int* ) = args . reduceLeft ( _ + _ ) // varargs. must be last arg def capitalizeAll ( args : String* ) = { args . map { arg => arg . capitalize } } capitalizeAll ( \"rarity\" , \"applejack\" ) If you want a collection expanded into a vararg, add :_* def repeatedParameterMethod ( x : Int , y : String , z : Any* ) = { \"%d %ss can give you %s\" . format ( x , y , z . mkString ( \", \" )) } repeatedParameterMethod ( 3 , \"egg\" , List ( \"a delicious sandwich\" , \"protein\" , \"high cholesterol\" ) :_ * ) should be ( __ )","title":"Variable Length Arguments"},{"location":"Scala/Scala_Language/#tail-recursion","text":"As a precaution, the helpful @tailrec annotation will throw a compile time if a method is not tail recursive, meaning that the last call and only call of the method is the recursive method. Scala optimizes recursive calls to a loop from a stack import scala.annotation.tailrec // importing annotation! @tailrec // compiler will check that the function is tail recursive def factorial ( i : BigInt ) : BigInt = { @tailrec def fact ( i : BigInt , accumulator : BigInt ) : BigInt = { // methods can be placed inside in methods; return type is obligatory if ( i <= 1 ) accumulator else fact ( i - 1 , i * accumulator ) } fact ( i , 1 ) } factorial ( 3 )","title":"Tail recursion"},{"location":"Scala/Scala_Language/#infix-postfix-and-prefix-notations-operators","text":"object FrenchDate { def main ( args : Array [ String ]) { val now = new Date val df = getDateInstance ( LONG , Locale . FRANCE ) println ( df format now ) // Methods taking one argument can be used with an infix syntax. Equivalent to df.format(now) } } 1 + 2 * 3 / x consists exclusively of method calls, because it is equivalent to the following expression: (1).+(((2).*(3))./(x)) This also means that +, *, etc. are valid identifiers in Scala. Infix Operators do NOT work if an object has a method that takes two parameters. val g : Int = 31 val s : String = g toHexString // Postfix operators work if an object has a method that takes no parameters Prefix operators work if an object has a method name that starts with unary_ class Stereo { def unary_+ = \"on\" def unary_- = \"off\" } val stereo = new Stereo + stereo // it is on Methods with colons are right-associative, that means the object that a method is on will be on the right and the method parameter will be on the left class Foo ( y : Int ) { def ~:( n : Int ) = n + y + 3 } val foo = new Foo ( 9 ) 10 ~: foo foo .~:( 10 ) // same as","title":"Infix, Postfix and Prefix Notations; Operators"},{"location":"Scala/Scala_Language/#anonymous-functions","text":"def lambda = ( x : Int ) => x + 1 // other variants def lambda2 = { x : Int => x + 1 } val lambda3 = new Function1 [ Int , Int ] { def apply ( v1 : Int ) : Int = v1 + 1 } val everything = () => 42 // without parameter val add = ( x : Int , y : Int ) => x + y // multiple parameters ( 1 to 5 ). map ( _ * 2 ) // underscore notation. ( 1 to 5 ) map ( _ * 2 ) // same with infix sugar. ( 1 to 5 ). reduceLeft ( _ + _ ) // underscores are positionally matched 1st and 2nd args. ( 1 to 5 ). map ( x => x * x ) // to use an arg twice, have to name it. ( 1 to 5 ). map { x => val y = x * 2 ; println ( y ); y } // block style returns last expression. ( 1 to 5 ) filter { _ % 2 == 0 } map { _ * 2 } // pipeline style (works with parens too). // GOOD (1 to 5).map(2*) // BAD (1 to 5).map(*2) // anonymous function: bound infix method. Use 2*_ for sanity\u2019s sake instead. def compose ( g : R => R , h : R => R ) = ( x : R ) => g ( h ( x )) val f = compose ({ _ * 2 }, { _ - 1 }) // anonymous functions: to pass in multiple blocks, need outer parens. Passing anonymous functions as parameter: def makeWhatEverYouLike ( xs : List [ String ], func : String => String ) = { xs map func } Function returning another function using an anonymous function: def add ( x : Int ) = ( y : Int ) => x + y Function Values: object Timer { def oncePerSecond ( callback : () => Unit ) { // () => T is a Function type that takes a Unit type. Unit is known as 'void' to a Java programmer. while ( true ) { callback (); Thread sleep 1000 } } def timeFlies () { println ( \"time flies like an arrow...\" ) } def main ( args : Array [ String ]) { oncePerSecond ( timeFlies ) // function value; could also be () => timeFlies() } }","title":"Anonymous Functions"},{"location":"Scala/Scala_Language/#by-name-parameter","text":"This is used extensively in scala to create blocks. def calc ( x : => Int ) : Either [ Throwable , Int ] = { //x is a call by name parameter; delayed execution of x try { Right ( x ) } catch { case b : Throwable => Left ( b ) } } val y = calc { //This looks like a natural block println ( \"Here we go!\" ) //Some superfluous call 49 + 20 } By name parameters can also be used with an Object and apply to make interesting block-like calls object PigLatinizer { def apply ( x : => String ) = x . tail + x . head + \"ay\" } val result = PigLatinizer { val x = \"pret\" val z = \"zel\" x ++ z //concatenate the strings }","title":"By-name parameter"},{"location":"Scala/Scala_Language/#closures","text":"var incrementer = 1 def closure = { x : Int => x + incrementer }","title":"Closures"},{"location":"Scala/Scala_Language/#currying","text":"val zscore = ( mean : R , sd : R ) => ( x : R ) => ( x - mean )/ sd // currying, obvious syntax. def zscore ( mean : R , sd : R ) = ( x : R ) => ( x - mean )/ sd // currying, obvious syntax def zscore ( mean : R , sd : R )( x : R ) = ( x - mean )/ sd // currying, sugar syntax. but then: val normer = zscore ( 7 , 0.4 ) _ // need trailing underscore to get the partial, only for the sugar version. def mapmake [ T ]( g : T => T )( seq : List [ T ]) = seq . map ( g ) // generic type. def multiply ( x : Int , y : Int ) = x * y val multiplyCurried = ( multiply _ ). curried multiply ( 4 , 5 ) multiplyCurried ( 3 )( 2 )","title":"Currying"},{"location":"Scala/Scala_Language/#partial-applications","text":"def adder ( m : Int , n : Int ) = m + n val add2 = adder ( 2 , _: Int ) // You can partially apply any argument in the argument list, not just the last one. add2 ( 3 ) // which is 5 val add3 = adder _ // underscore to convert from a function to a lambda adder ( 1 , 9 ) add3 ( 1 , 9 )","title":"Partial Applications"},{"location":"Scala/Scala_Language/#partial-functions","text":"val doubleEvens : PartialFunction [ Int , Int ] = new PartialFunction [ Int , Int ] { // full declaration //States that this partial function will take on the task def isDefinedAt ( x : Int ) = x % 2 == 0 //What we do if this does partial function matches def apply ( v1 : Int ) = v1 * 2 } val tripleOdds : PartialFunction [ Int , Int ] = { case x : Int if ( x % 2 ) != 0 => x * 3 // syntaxic sugar (usual way) } val whatToDo = doubleEvens orElse tripleOdds // combine the partial functions together: OrElse val addFive = ( x : Int ) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive // chain (partial) functions together: andThen","title":"Partial Functions"},{"location":"Scala/Scala_Language/#classes-objects-and-traits","text":"class C ( x : R ) // constructor params - x is only available in class body class C ( val x : R ) // c.x constructor params - automatic public (immutable) member defined class D ( var x : R ) // you can define class with var or val parameters class C ( var x : R ) { assert ( x > 0 , \"positive please\" ) // constructor is class body var y = x // declare a public member val readonly = 5 // declare a gettable but not settable member private var secret = 1 // declare a private member def this = this ( 42 ) // alternative constructor } new { ... } // anonymous class abstract class D { ... } // define an abstract(non-createable) class. class C extends D { ... } // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class class C ( x : R ) extends D ( x ) // inheritance and constructor params. (wishlist: automatically pass-up params by default) // A class can be placed inside another class object O extends D { ... } // define a singleton. trait T { ... } // traits. See below. class C extends T { ... } class C extends D with T { ... } // interfaces-with-implementation. no constructor params. mixin-able. trait T1 ; trait T2 class C extends T1 with T2 // multiple traits. class C extends D with T1 with T2 // parent class and (multiple) trait(s). class C extends D { override def f = ...} // must declare method overrides. var c = new C ( 4 ) // Instantiation //BAD new List[Int] //GOOD List(1,2,3) // Instead, convention: callable factory shadowing the type classOf [ String ] // class literal. classOf [ String ]. getCanonicalName classOf [ String ]. getSimpleName val zoom = \"zoom\" zoom . getClass == classOf [ String ] x . isInstanceOf [ String ] // type check (runtime) x . asInstanceOf [ String ] // type cast (runtime) x : String // compare to parameter ascription (compile time)","title":"Classes, Objects, and Traits"},{"location":"Scala/Scala_Language/#methods","text":"class Complex ( real : Double , imaginary : Double ) { def re = real // return type inferred automatically by the compiler def im = imaginary // methods without arguments def print () : Unit = println ( s\" $real + i * $imaginary \" ) override def toString () = \"\" + re + ( if ( im < 0 ) \"\" else \"+\" ) + im + \"i\" // override methods inherited from a super-class }","title":"Methods"},{"location":"Scala/Scala_Language/#asserts-and-contracts","text":"Asserts take a boolean argument and can take a message. assert ( true ) // should be true assert ( true , \"This should be true\" ) def addNaturals ( nats : List [ Int ]) : Int = { require ( nats forall ( _ >= 0 ), \"List contains negative numbers\" ) nats . foldLeft ( 0 )( _ + _ ) } ensuring ( _ >= 0 )","title":"Asserts and Contracts"},{"location":"Scala/Scala_Language/#path-dependent-classes","text":"When a class is instantiated inside of another object, it belongs to the instance. This is a path dependent type. Once established, it cannot be placed inside of another object case class Board ( length : Int , height : Int ) { case class Coordinate ( x : Int , y : Int ) } val b1 = Board ( 20 , 20 ) val b2 = Board ( 30 , 30 ) val c1 = b1 . Coordinate ( 15 , 15 ) val c2 = b2 . Coordinate ( 25 , 25 ) // val c1 = c2 won't work Use A#B for a Java-style inner class: class Graph { class Node { var connectedNodes : List [ Graph # Node ] = Nil // accepts Nodes from any Graph def connectTo ( node : Graph # Node ) { if ( connectedNodes . find ( node . equals ). isEmpty ) { connectedNodes = node :: connectedNodes } } } var nodes : List [ Node ] = Nil def newNode : Node = { val res = new Node nodes = res :: nodes res } }","title":"Path-dependent Classes"},{"location":"Scala/Scala_Language/#companion-objects","text":"Static members (methods or fields) do not exist in Scala. Rather than defining static members, the Scala programmer declares these members in singleton objects, that is a class with a single instance. object TimerAnonymous { def oncePerSecond ( callback : () => Unit ) { while ( true ) { callback (); Thread sleep 1000 } } def main ( args : Array [ String ]) { oncePerSecond (() => println ( \"time flies like an arrow...\" )) } } An object that has the same name as class is called a companion object, it is used to contain factories for the class that it complements. A companion object can also store shared variables and values for every instantiated class to share. A companion object can see private values and variables of the instantiated object","title":"Companion Objects"},{"location":"Scala/Scala_Language/#apply-method","text":"The apply method is a magical method in Scala. class Employee ( val firstName : String , val lastName : String ) object Employee { def apply ( firstName : String , lastName : String ) = new Employee ( firstName , lastName ) // would also work in a class, but rarer } val a = Employee ( \"John\" , \"Doe\" ) // is equivalent to var b = Employee . apply ( \"John\" , \"Doe\" )","title":"Apply Method"},{"location":"Scala/Scala_Language/#case-classes","text":"The new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)), Getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v), Default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity, A default definition for method toString is provided, and prints the value in a source form (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))), Instances of these classes can be decomposed through pattern matching case class Person ( first : String , last : String , age : Int = 0 ) // Case classes can have default and named parameters val p1 = Person ( \"Fred\" , \"Jones\" ) // new is optional val p2 = new Person ( \"Fred\" , \"Jones\" ) p1 == p2 // true p1 . hashCode == p2 . hashCode // true p1 eq p2 // false val p3 = p2 . copy ( first = \"Jane\" ) // copy the case class but change the name in the copy case class Dog ( var name : String , breed : String ) // Case classes can have mutable properties - potentially unsafe Case classes can be disassembled to their constituent parts as a tuple: val parts = Person . unapply ( p1 ). get // returns Option[T] parts . _1 parts . _2","title":"Case Classes"},{"location":"Scala/Scala_Language/#algebraic-data-type","text":"sealed trait Tree // or abstract class final case class Sum ( l : Tree , r : Tree ) extends Tree final case class Var ( n : String ) extends Tree final case class Const ( v : Int ) extends Tree","title":"Algebraic data type"},{"location":"Scala/Scala_Language/#pattern-matching","text":"{ case \"x\" => 5 } defines a partial function which, when given the string \"x\" as argument, returns the integer 5, and fails with an exception otherwise. type Environment = String => Int // the type Environment can be used as an alias of the type of functions from String to Int def eval ( t : Tree , env : Environment ) : Int = t match { case Sum ( l , r ) => eval ( l , env ) + eval ( r , env ) case Var ( n ) => env ( n ) case Const ( v ) => v } def derive ( t : Tree , v : String ) : Tree = t match { case Sum ( l , r ) => Sum ( derive ( l , v ), derive ( r , v )) case Var ( n ) if ( v == n ) => Const ( 1 ) // guard, an expression following the if keyword. case _ => Const ( 0 ) // wild-card, written _, which is a pattern matching any value, without giving it a name. } // GOOD (xs zip ys) map { case (x,y) => x*y } // BAD (xs zip ys) map( (x,y) => x*y ) // use case in function args for pattern matching. // BAD val v42 = 42 Some ( 3 ) match { case Some ( v42 ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // \u201cv42\u201d is interpreted as a name matching any Int value, and \u201c42\u201d is printed. // GOOD val v42 = 42 Some ( 3 ) match { case Some ( `v42` ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // \u201d`v42`\u201d with backticks is interpreted as the existing val v42, and \u201cNot 42\u201d is printed. // GOOD val UppercaseVal = 42 Some ( 3 ) match { case Some ( UppercaseVal ) => println ( \"42\" ) case _ => println ( \"Not 42\" ) } // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter. // Thus, the value contained within UppercaseVal is checked against 3, and \u201cNot 42\u201d is printed.","title":"Pattern Matching"},{"location":"Scala/Scala_Language/#list-matching","text":"val secondElement = List ( 1 , 2 , 3 ) match { case x :: y :: xs => xs case x :: Nil => x case _ => 0 }","title":"List Matching"},{"location":"Scala/Scala_Language/#regex","text":"val MyRegularExpression = \"\"\"a=([^,]+),\\s+b=(.+)\"\"\" . r //.r turns a String to a regular expression expr match { case ( MyRegularExpression ( a , b )) => a + b } import scala.util.matching.Regex val numberPattern : Regex = \"[0-9]\" . r numberPattern . findFirstMatchIn ( \"awesomepassword\" ) match { case Some ( _ ) => println ( \"Password OK\" ) case None => println ( \"Password must contain a number\" ) } With groups: val keyValPattern : Regex = \"([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)\" . r for ( patternMatch <- keyValPattern . findAllMatchIn ( input )) println ( s\"key: ${ patternMatch . group ( 1 ) } value: ${ patternMatch . group ( 2 ) } \" )","title":"Regex"},{"location":"Scala/Scala_Language/#extractors-unapply","text":"class Car ( val make : String , val model : String , val year : Short , val topSpeed : Short ) object Car { // What is typical is to create a custom extractor in the companion object of the class. def unapply ( x : Car ) = Some ( x . make , x . model , x . year , x . topSpeed ) // returns an Option[T] } val Car ( a , b , c , d ) = new Car ( \"Chevy\" , \"Camaro\" , 1978 , 120 ) // assign values to a .. d val x = new Car ( \"Chevy\" , \"Camaro\" , 1978 , 120 ) match { // pattern matching case Car ( s , t , _ , _ ) => ( s , t ) // _ for variables we don't care about. case _ => ( \"Ford\" , \"Edsel\" ) // fallback } As long as the method signatures aren't the same, you can have an many unapply methods as you want in the same class / object. When you create a case class, it automatically can be used with pattern matching since it has an extractor.","title":"Extractors (unapply)"},{"location":"Scala/Scala_Language/#value-class","text":"Avoid allocating runtime objects. class Wrapper ( val underlying : Int ) extends AnyVal { def foo : Wrapper = new Wrapper ( underlying * 19 ) } It has a single, public val parameter that is the underlying runtime representation. The type at compile time is Wrapper, but at runtime, the representation is an Int. A value class can define defs, but no vals, vars, or nested traitss, classes or objects A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation.","title":"Value Class"},{"location":"Scala/Scala_Language/#traits","text":"Apart from inheriting code from a super-class, a Scala class can also import code from one or several traits i.e. interfaces which can also contain code. In Scala, when a class inherits from a trait, it implements that traits's interface, and inherits all the code contained in the trait. trait Ord { def < ( that : Any ) : Boolean // The type Any which is used above is the type which is a super-type of all other types in Scala def <= ( that: Any ) : Boolean = ( this < that ) || ( this == that ) def > ( that : Any ) : Boolean = !( this <= that ) def >=( that : Any ) : Boolean = !( this < that ) } class Date ( y : Int , m : Int , d : Int ) extends Ord { def year = y def month = m def day = d override def toString () : String = year + \"-\" + month + \"-\" + day override def equals ( that : Any ) : Boolean = that . isInstanceOf [ Date ] && { val o = that . asInstanceOf [ Date ] o . day == day && o . month == month && o . year == year } def <( that : Any ) : Boolean = { // The trait declare the type (e.g. method), where a concrete implementer will satisfy the type if (! that . isInstanceOf [ Date ]) error ( \"cannot compare \" + that + \" and a Date\" ) val o = that . asInstanceOf [ Date ]( year < o . year ) || ( year == o . year && ( month < o . month || ( month == o . month && day < o . day ))) } } Traits can have concrete implementations that can be mixed into concrete classes with its own state Traits can be mixed in during instantiation! trait Logging { var logCache = List [ String ]() def log ( value : String ) = { logCache = logCache :+ value } def log = logCache } val a = new A ( \"stuff\" ) with Logging // mixin traits during instantiation! a . log ( \"I did something\" ) a . log . size","title":"Traits"},{"location":"Scala/Scala_Language/#stackable-traits","text":"abstract class IntQueue { def get () : Int def put ( x : Int ) } import scala.collection.mutable.ArrayBuffer class BasicIntQueue extends IntQueue { private val buf = new ArrayBuffer [ Int ] def get () = buf . remove ( 0 ) def put ( x : Int ) { buf += x } } trait Doubling extends IntQueue { abstract override def put ( x : Int ) { super . put ( 2 * x ) } // abstract override is necessary to stack traits } class MyQueue extends BasicIntQueue with Doubling // could also mixin during instantiation val myQueue = new MyQueue myQueue . put ( 3 ) myQueue . get () More traits can be stacked one atop another, make sure that all overrides are labelled abstract override . The order of the mixins are important. Traits on the right take effect first. Traits are instantiated before a classes instantiation from left to right. Linerization: the diamond inheritance problem is avoided since instantiations are tracked and will not allow multiple instantiations of the same parent trait","title":"Stackable Traits"},{"location":"Scala/Scala_Language/#classes-versus-traits","text":"Use classes: When a behavior is not going to be reused at all or in multiple places When you plan to use your Scala code from another language, for example, if you are building a library that could be used in Java Use traits: When a behavior is going to be reused in multiple unrelated classes. When you want to define interfaces and want to use them outside Scala, for example Java. The reason is that the traits that do not have any implementations are compiled similar to interfaces.","title":"Classes versus Traits"},{"location":"Scala/Scala_Language/#keyword-list","text":"abstract case catch class def do else extends false final finally for forSome if implicit import lazy match new Null object override package private protected return sealed super this throw trait Try true type val var while with yield - : = => <- <: <% >: # @","title":"Keyword List"},{"location":"Scala/Scala_Testing/","text":"Links \u00b6 http://www.scalatest.org/ Writing TDD unit tests with scalatest At a Glance Examples \u00b6 libraryDependencies += \"org.scalatest\" %% \"scalatest\" % \"2.2.6\" % \"test\" package com.acme.pizza import org.scalatest.FunSuite import org.scalatest.BeforeAndAfter class PizzaTests extends FunSuite with BeforeAndAfter { var pizza : Pizza = _ before { pizza = new Pizza } test ( \"new pizza has zero toppings\" ) { assert ( pizza . getToppings . size == 0 ) } test ( \"adding one topping\" ) { pizza . addTopping ( Topping ( \"green olives\" )) assert ( pizza . getToppings . size === 1 ) } // mark that you want a test here in the future test ( \"test pizza pricing\" ) ( pending ) } Styles \u00b6 FunSuite \u00b6 import org.scalatest.FunSuite class AddSuite extends FunSuite { test ( \"3 plus 3 is 6\" ) { assert (( 3 + 3 ) == 6 ) } } FlatSpec \u00b6 The structure of this test is flat\u2014like xUnit, but the test name can be written in specification style: import org.scalatest.FlatSpec class AddSpec extends FlatSpec { \"Addition of 3 and 3\" should \"have result 6\" in { assert (( 3 + 3 ) == 0 ) } } import collection.mutable.Stack import org.scalatest._ class ExampleSpec extends FlatSpec with Matchers { \"A Stack\" should \"pop values in last-in-first-out order\" in { val stack = new Stack [ Int ] stack . push ( 1 ) stack . push ( 2 ) stack . pop () should be ( 2 ) stack . pop () should be ( 1 ) } it should \"throw NoSuchElementException if an empty stack is popped\" in { val emptyStack = new Stack [ Int ] a [ NoSuchElementException ] should be thrownBy { emptyStack . pop () } } } FeatureSpec \u00b6 import org.scalatest._ class Calculator { def add ( a : Int , b : Int ) : Int = a + b } class CalcSpec extends FeatureSpec with GivenWhenThen { info ( \"As a calculator owner\" ) info ( \"I want to be able add two numbers\" ) info ( \"so I can get a correct result\" ) feature ( \"Addition\" ) { scenario ( \"User adds two numbers\" ) { Given ( \"a calculator\" ) val calc = new Calculator When ( \"two numbers are added\" ) var result = calc . add ( 3 , 3 ) Then ( \"we get correct result\" ) assert ( result == 6 ) } } }","title":"Scala Testing"},{"location":"Scala/Scala_Testing/#links","text":"http://www.scalatest.org/ Writing TDD unit tests with scalatest At a Glance","title":"Links"},{"location":"Scala/Scala_Testing/#examples","text":"libraryDependencies += \"org.scalatest\" %% \"scalatest\" % \"2.2.6\" % \"test\" package com.acme.pizza import org.scalatest.FunSuite import org.scalatest.BeforeAndAfter class PizzaTests extends FunSuite with BeforeAndAfter { var pizza : Pizza = _ before { pizza = new Pizza } test ( \"new pizza has zero toppings\" ) { assert ( pizza . getToppings . size == 0 ) } test ( \"adding one topping\" ) { pizza . addTopping ( Topping ( \"green olives\" )) assert ( pizza . getToppings . size === 1 ) } // mark that you want a test here in the future test ( \"test pizza pricing\" ) ( pending ) }","title":"Examples"},{"location":"Scala/Scala_Testing/#styles","text":"","title":"Styles"},{"location":"Scala/Scala_Testing/#funsuite","text":"import org.scalatest.FunSuite class AddSuite extends FunSuite { test ( \"3 plus 3 is 6\" ) { assert (( 3 + 3 ) == 6 ) } }","title":"FunSuite"},{"location":"Scala/Scala_Testing/#flatspec","text":"The structure of this test is flat\u2014like xUnit, but the test name can be written in specification style: import org.scalatest.FlatSpec class AddSpec extends FlatSpec { \"Addition of 3 and 3\" should \"have result 6\" in { assert (( 3 + 3 ) == 0 ) } } import collection.mutable.Stack import org.scalatest._ class ExampleSpec extends FlatSpec with Matchers { \"A Stack\" should \"pop values in last-in-first-out order\" in { val stack = new Stack [ Int ] stack . push ( 1 ) stack . push ( 2 ) stack . pop () should be ( 2 ) stack . pop () should be ( 1 ) } it should \"throw NoSuchElementException if an empty stack is popped\" in { val emptyStack = new Stack [ Int ] a [ NoSuchElementException ] should be thrownBy { emptyStack . pop () } } }","title":"FlatSpec"},{"location":"Scala/Scala_Testing/#featurespec","text":"import org.scalatest._ class Calculator { def add ( a : Int , b : Int ) : Int = a + b } class CalcSpec extends FeatureSpec with GivenWhenThen { info ( \"As a calculator owner\" ) info ( \"I want to be able add two numbers\" ) info ( \"so I can get a correct result\" ) feature ( \"Addition\" ) { scenario ( \"User adds two numbers\" ) { Given ( \"a calculator\" ) val calc = new Calculator When ( \"two numbers are added\" ) var result = calc . add ( 3 , 3 ) Then ( \"we get correct result\" ) assert ( result == 6 ) } } }","title":"FeatureSpec"},{"location":"Scala/Scala_Types/","text":"Type Refinement \u00b6 Type Refinement = \"subclassing without naming the subclass\". class Entity trait Persister { def doPersist ( e : Entity ) = { e . persistForReal () } } // our refined instance (and type): val refinedMockPersister = new Persister { override def doPersist ( e : Entity ) = () } Scala Types of Types Generics \u00b6 class Reference [ T ] { private var contents : T = _ // _ represents a default value. This default value is 0 for numeric types, false for the Boolean type, () for the Unit type and null for all object types. def set ( value : T ) { contents = value } def get : T = contents } trait Cache [ K , V ] { def get ( key : K ) : V def put ( key : K , value : V ) def delete ( key : K ) } def remove [ K ]( key : K ) // function Type Variance \u00b6 Covariance +A allow you to set the your container to a either a variable with the same type or parent type. class MyContainer [ +A ]( a : A )( implicit manifest : scala.reflect.Manifest [ A ]) { private [ this ] val item = a def get = item def contents = manifest . runtimeClass . getSimpleName } val fruitBasket : MyContainer [ Fruit ] = new MyContainer [ Orange ]( new Orange ()) fruitBasket . contents Contravariance -A is the opposite of covariance Declaring neither -/+, indicates invariance variance. You cannot use a superclass variable reference (\"contravariant\" position) or a subclass variable reference (\"covariant\" position) of that type. Upper and Lower Type Bounds \u00b6 abstract class Pet extends Animal { def name : String } class Cat extends Pet { override def name : String = \"Cat\" } class PetContainer [ P <: Pet ]( p : P ) { def pet : P = p // The class PetContainer take a type parameter P which must be a subtype of Pet. } Lower type bounds declare a type to be a supertype of another type. The term B >: A expresses that the type parameter B or the abstract type B refer to a supertype of type A. Abstract Types \u00b6 type R = Double // type alias trait Container { type T val data : T def compare ( other : T ) = data . equals ( other ) } class StringContainer ( val data : String ) extends Container { override type T = String } Generics vs Abstract Types \u00b6 Generics: If you need just type instantiation. A good example is the standard collection classes. If you are creating a family of types. Abstract types: If you want to allow people to mix in types using traits. If you need better readability in scenarios where both could be interchangeable. If you want to hide the type definition from the client code. Infix Type \u00b6 We can make a type infix, meaning that a generic type with two type parameters can be displayed between two types. The type specifier Pair[String,Int] can be written as String Pair Int . class Pair [ A , B ]( a : A , b : B ) type ~ [ A , B ] = Pair [ A , B ] val pairlist : List [ String ~ Int ] // operator-like usage case class Item [ T ]( i : T ) { def ~( j : Item [ T ]) = new Pair ( this , j ) // creating an infix operator method to use with our infix type } ( Item ( \"a\" ) ~ Item ( \"b\" )). isInstanceOf [ String ~ String ] ShapeLess Structural Types \u00b6 import scala.language.reflectiveCalls // use reflection --> slow def onlyThoseThatCanPerformQuacks ( quacker : { def quack:String }) : String = { \"received message: %s\" . format ( quacker . quack ) } type SpeakerAndMover = { def speak : String ; def move ( steps : Int , direction : String ) : String } // with type aliasing Self-type \u00b6 Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn\u2019t directly extend it. That makes the members of the dependency available without imports. trait User { def username : String } trait Tweeter { this: User => // reassign this def tweet ( tweetText : String ) = println ( s\" $username : $tweetText \" ) } class VerifiedTweeter ( val username_ : String ) extends Tweeter with User { // We mixin User because Tweeter required it def username = s\"real $username_ \" } Difference between a self type and extending a trait \u00b6 If you say that B extends A, then B is an A. When you use self-types, B requires an A. There are two specific requirements that are created with self-types: 1. If B is extended, then you're required to mix-in an A. 1. When a concrete class finally extends/mixes-in these traits, some class/trait must implement A. trait Wrong extends Tweeter { def noCanDo = name // does not compile } If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error. Self types allow you to define cyclical dependencies. For example, you can achieve this: trait A { self : B => } trait B { self : A => } Inheritance using extends does not allow that. Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as: sealed trait Person trait Student extends Person trait Teacher extends Person trait Adult { this : Person => } // orthogonal to its condition val p : Person = new Student {} p match { case s : Student => println ( \"a student\" ) case t : Teacher => println ( \"a teacher\" ) } // that's it we're exhaustive Implicits \u00b6 Implicits wrap around existing classes to provide extra functionality object MyPredef { // usually in a companion object class IntWrapper ( val original : Int ) { def isOdd = original % 2 != 0 def isEven = ! isOdd } implicit def thisMethodNameIsIrrelevant ( value : Int ) = new IntWrapper ( value ) } import MyPredef._ //imported implicits come into effect within this scope 19. isOdd // Implicits can be used to automatically convert one type to another import java.math.BigInteger implicit def Int2BigIntegerConvert ( value : Int ) : BigInteger = new BigInteger ( value . toString ) def add ( a : BigInteger , b : BigInteger ) = a . add ( b ) add ( 3 , 6 ) // 3 and 6 are Int // Implicits function parameters def howMuchCanIMake_? ( hours : Int )( implicit amount : BigDecimal , currencyName : String ) = ( amount * hours ). toString () + \" \" + currencyName implicit var hourlyRate = BigDecimal ( 34.00 ) implicit val currencyName = \"Dollars\" howMuchCanIMake_? ( 30 ) Default arguments though are preferred to Implicit Function Parameters. Context-bound Types \u00b6 def inspect [ T : TypeTag ]( l : List [ T ]) = typeOf [ T ]. typeSymbol . name . decoded val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect ( list ) equivalent to def inspect [ T ]( l : List [ T ])( implicit tt : TypeTag [ T ]) = tt . tpe . typeSymbol . name . decoded val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect ( list ) TypeTags can be used to determine a type used before it erased by the VM by using an implicit TypeTag argument.","title":"Scala Types"},{"location":"Scala/Scala_Types/#type-refinement","text":"Type Refinement = \"subclassing without naming the subclass\". class Entity trait Persister { def doPersist ( e : Entity ) = { e . persistForReal () } } // our refined instance (and type): val refinedMockPersister = new Persister { override def doPersist ( e : Entity ) = () } Scala Types of Types","title":"Type Refinement"},{"location":"Scala/Scala_Types/#generics","text":"class Reference [ T ] { private var contents : T = _ // _ represents a default value. This default value is 0 for numeric types, false for the Boolean type, () for the Unit type and null for all object types. def set ( value : T ) { contents = value } def get : T = contents } trait Cache [ K , V ] { def get ( key : K ) : V def put ( key : K , value : V ) def delete ( key : K ) } def remove [ K ]( key : K ) // function","title":"Generics"},{"location":"Scala/Scala_Types/#type-variance","text":"Covariance +A allow you to set the your container to a either a variable with the same type or parent type. class MyContainer [ +A ]( a : A )( implicit manifest : scala.reflect.Manifest [ A ]) { private [ this ] val item = a def get = item def contents = manifest . runtimeClass . getSimpleName } val fruitBasket : MyContainer [ Fruit ] = new MyContainer [ Orange ]( new Orange ()) fruitBasket . contents Contravariance -A is the opposite of covariance Declaring neither -/+, indicates invariance variance. You cannot use a superclass variable reference (\"contravariant\" position) or a subclass variable reference (\"covariant\" position) of that type.","title":"Type Variance"},{"location":"Scala/Scala_Types/#upper-and-lower-type-bounds","text":"abstract class Pet extends Animal { def name : String } class Cat extends Pet { override def name : String = \"Cat\" } class PetContainer [ P <: Pet ]( p : P ) { def pet : P = p // The class PetContainer take a type parameter P which must be a subtype of Pet. } Lower type bounds declare a type to be a supertype of another type. The term B >: A expresses that the type parameter B or the abstract type B refer to a supertype of type A.","title":"Upper and Lower Type Bounds"},{"location":"Scala/Scala_Types/#abstract-types","text":"type R = Double // type alias trait Container { type T val data : T def compare ( other : T ) = data . equals ( other ) } class StringContainer ( val data : String ) extends Container { override type T = String }","title":"Abstract Types"},{"location":"Scala/Scala_Types/#generics-vs-abstract-types","text":"Generics: If you need just type instantiation. A good example is the standard collection classes. If you are creating a family of types. Abstract types: If you want to allow people to mix in types using traits. If you need better readability in scenarios where both could be interchangeable. If you want to hide the type definition from the client code.","title":"Generics vs Abstract Types"},{"location":"Scala/Scala_Types/#infix-type","text":"We can make a type infix, meaning that a generic type with two type parameters can be displayed between two types. The type specifier Pair[String,Int] can be written as String Pair Int . class Pair [ A , B ]( a : A , b : B ) type ~ [ A , B ] = Pair [ A , B ] val pairlist : List [ String ~ Int ] // operator-like usage case class Item [ T ]( i : T ) { def ~( j : Item [ T ]) = new Pair ( this , j ) // creating an infix operator method to use with our infix type } ( Item ( \"a\" ) ~ Item ( \"b\" )). isInstanceOf [ String ~ String ] ShapeLess","title":"Infix Type"},{"location":"Scala/Scala_Types/#structural-types","text":"import scala.language.reflectiveCalls // use reflection --> slow def onlyThoseThatCanPerformQuacks ( quacker : { def quack:String }) : String = { \"received message: %s\" . format ( quacker . quack ) } type SpeakerAndMover = { def speak : String ; def move ( steps : Int , direction : String ) : String } // with type aliasing","title":"Structural Types"},{"location":"Scala/Scala_Types/#self-type","text":"Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn\u2019t directly extend it. That makes the members of the dependency available without imports. trait User { def username : String } trait Tweeter { this: User => // reassign this def tweet ( tweetText : String ) = println ( s\" $username : $tweetText \" ) } class VerifiedTweeter ( val username_ : String ) extends Tweeter with User { // We mixin User because Tweeter required it def username = s\"real $username_ \" }","title":"Self-type"},{"location":"Scala/Scala_Types/#difference-between-a-self-type-and-extending-a-trait","text":"If you say that B extends A, then B is an A. When you use self-types, B requires an A. There are two specific requirements that are created with self-types: 1. If B is extended, then you're required to mix-in an A. 1. When a concrete class finally extends/mixes-in these traits, some class/trait must implement A. trait Wrong extends Tweeter { def noCanDo = name // does not compile } If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error. Self types allow you to define cyclical dependencies. For example, you can achieve this: trait A { self : B => } trait B { self : A => } Inheritance using extends does not allow that. Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as: sealed trait Person trait Student extends Person trait Teacher extends Person trait Adult { this : Person => } // orthogonal to its condition val p : Person = new Student {} p match { case s : Student => println ( \"a student\" ) case t : Teacher => println ( \"a teacher\" ) } // that's it we're exhaustive","title":"Difference between a self type and extending a trait"},{"location":"Scala/Scala_Types/#implicits","text":"Implicits wrap around existing classes to provide extra functionality object MyPredef { // usually in a companion object class IntWrapper ( val original : Int ) { def isOdd = original % 2 != 0 def isEven = ! isOdd } implicit def thisMethodNameIsIrrelevant ( value : Int ) = new IntWrapper ( value ) } import MyPredef._ //imported implicits come into effect within this scope 19. isOdd // Implicits can be used to automatically convert one type to another import java.math.BigInteger implicit def Int2BigIntegerConvert ( value : Int ) : BigInteger = new BigInteger ( value . toString ) def add ( a : BigInteger , b : BigInteger ) = a . add ( b ) add ( 3 , 6 ) // 3 and 6 are Int // Implicits function parameters def howMuchCanIMake_? ( hours : Int )( implicit amount : BigDecimal , currencyName : String ) = ( amount * hours ). toString () + \" \" + currencyName implicit var hourlyRate = BigDecimal ( 34.00 ) implicit val currencyName = \"Dollars\" howMuchCanIMake_? ( 30 ) Default arguments though are preferred to Implicit Function Parameters.","title":"Implicits"},{"location":"Scala/Scala_Types/#context-bound-types","text":"def inspect [ T : TypeTag ]( l : List [ T ]) = typeOf [ T ]. typeSymbol . name . decoded val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect ( list ) equivalent to def inspect [ T ]( l : List [ T ])( implicit tt : TypeTag [ T ]) = tt . tpe . typeSymbol . name . decoded val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect ( list ) TypeTags can be used to determine a type used before it erased by the VM by using an implicit TypeTag argument.","title":"Context-bound Types"},{"location":"Scala/Scaladoc/","text":"Scaladoc Scaladoc Style Guide /** Start the comment here * and use the left star followed by a * white space on every line. * * Even on empty paragraph-break lines. * * Note that the * on each line is aligned * with the second * in /** so that the * left margin is on the same column on the * first line and on subsequent ones. * * The closing Scaladoc tag goes on its own, * separate line. E.g. * * Calculate the square of the given number * * @param d the Double to square * @return the result of squaring d */ def square(d: Double): Double = d * d Tags \u00b6 Class specific tags \u00b6 @constructor placed in the class comment will describe the primary constructor. Method specific tags @return detail the return value from a method (one per method). Method, Constructor and/or Class tags @throws what exceptions (if any) the method or constructor may throw. @param detail a value parameter for a method or constructor, provide one per parameter to the method/constructor. @tparam detail a type parameter for a method, constructor or class. Provide one per type parameter. Usage tags \u00b6 @see reference other sources of information like external document links or related entities in the documentation. @note add a note for pre or post conditions, or any other notable restrictions or expectations. @example for providing example code or related example documentation. @usecase provide a simplified method definition for when the full method definition is too complex or noisy. An example is (in the collections API), providing documentation for methods that omit the implicit canBuildFrom. Member grouping tags \u00b6 @group - mark the entity as a member of the group. @groupname - provide an optional name for the group. is displayed as the group header before the group description. @groupdesc - add optional descriptive text to display under the group name. Supports multiline formatted text. @groupprio - control the order of the group on the page. Defaults to 0. Ungrouped elements have an implicit priority of 1000. Use a value between 0 and 999 to set a relative position to other groups. Low values will appear before high values. Diagram tags \u00b6 @contentDiagram - use with traits and classes to include a content hierarchy diagram showing included types. The diagram content can be fine tuned with additional specifiers taken from hideNodes, hideOutgoingImplicits, hideSubclasses, hideEdges, hideIncomingImplicits, hideSuperclasses and hideInheritedNode. hideDiagram can be supplied to prevent a diagram from being created if it would be created by default. Packages and objects have content diagrams by default. @inheritanceDiagram Other tags \u00b6 @author provide author information for the following entity @version the version of the system or API that this entity is a part of. @since like @version but defines the system or API that this entity was first defined in. @todo for documenting unimplemented features or unimplemented aspects of an entity. @deprecated marks the entity as deprecated, providing both the replacement implementation that should be used and the version/date at which this entity was deprecated. @migration like deprecated but provides advanced warning of planned changes ahead of deprecation. Same fields as @deprecated . @inheritdoc take comments from a superclass as defaults if comments are not provided locally. @documentable Expand a type alias and abstract type into a full template page. - TODO: Test the \u201cabstract type\u201d claim - no examples of this in the Scala code base Macros \u00b6 @define allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of . Markup \u00b6 `monospace` ''italic text'' '''bold text''' __underline__ ^superscript^ ,,subscript,, [[entity link]], e.g. [[scala.collection.Seq]] [[http://external.link External Link]], e.g. [[http://scala-lang.org Scala Language Site]] Other formatting notes \u00b6 Paragraphs are started with one (or more) blank lines. * in the margin for the comment is valid (and should be included) but the line should be blank otherwise. Code blocks are contained within {{{ this }}} and may be multi-line. Indentation is relative to the starting * for the comment. Headings are defined with surrounding = characters, with more = denoting subheadings. E.g. =Heading=, ==Sub-Heading==, etc. List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles.","title":"Scaladoc"},{"location":"Scala/Scaladoc/#tags","text":"","title":"Tags"},{"location":"Scala/Scaladoc/#class-specific-tags","text":"@constructor placed in the class comment will describe the primary constructor. Method specific tags @return detail the return value from a method (one per method). Method, Constructor and/or Class tags @throws what exceptions (if any) the method or constructor may throw. @param detail a value parameter for a method or constructor, provide one per parameter to the method/constructor. @tparam detail a type parameter for a method, constructor or class. Provide one per type parameter.","title":"Class specific tags"},{"location":"Scala/Scaladoc/#usage-tags","text":"@see reference other sources of information like external document links or related entities in the documentation. @note add a note for pre or post conditions, or any other notable restrictions or expectations. @example for providing example code or related example documentation. @usecase provide a simplified method definition for when the full method definition is too complex or noisy. An example is (in the collections API), providing documentation for methods that omit the implicit canBuildFrom.","title":"Usage tags"},{"location":"Scala/Scaladoc/#member-grouping-tags","text":"@group - mark the entity as a member of the group. @groupname - provide an optional name for the group. is displayed as the group header before the group description. @groupdesc - add optional descriptive text to display under the group name. Supports multiline formatted text. @groupprio - control the order of the group on the page. Defaults to 0. Ungrouped elements have an implicit priority of 1000. Use a value between 0 and 999 to set a relative position to other groups. Low values will appear before high values.","title":"Member grouping tags"},{"location":"Scala/Scaladoc/#diagram-tags","text":"@contentDiagram - use with traits and classes to include a content hierarchy diagram showing included types. The diagram content can be fine tuned with additional specifiers taken from hideNodes, hideOutgoingImplicits, hideSubclasses, hideEdges, hideIncomingImplicits, hideSuperclasses and hideInheritedNode. hideDiagram can be supplied to prevent a diagram from being created if it would be created by default. Packages and objects have content diagrams by default. @inheritanceDiagram","title":"Diagram tags"},{"location":"Scala/Scaladoc/#other-tags","text":"@author provide author information for the following entity @version the version of the system or API that this entity is a part of. @since like @version but defines the system or API that this entity was first defined in. @todo for documenting unimplemented features or unimplemented aspects of an entity. @deprecated marks the entity as deprecated, providing both the replacement implementation that should be used and the version/date at which this entity was deprecated. @migration like deprecated but provides advanced warning of planned changes ahead of deprecation. Same fields as @deprecated . @inheritdoc take comments from a superclass as defaults if comments are not provided locally. @documentable Expand a type alias and abstract type into a full template page. - TODO: Test the \u201cabstract type\u201d claim - no examples of this in the Scala code base","title":"Other tags"},{"location":"Scala/Scaladoc/#macros","text":"@define allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of .","title":"Macros"},{"location":"Scala/Scaladoc/#markup","text":"`monospace` ''italic text'' '''bold text''' __underline__ ^superscript^ ,,subscript,, [[entity link]], e.g. [[scala.collection.Seq]] [[http://external.link External Link]], e.g. [[http://scala-lang.org Scala Language Site]]","title":"Markup"},{"location":"Scala/Scaladoc/#other-formatting-notes","text":"Paragraphs are started with one (or more) blank lines. * in the margin for the comment is valid (and should be included) but the line should be blank otherwise. Code blocks are contained within {{{ this }}} and may be multi-line. Indentation is relative to the starting * for the comment. Headings are defined with surrounding = characters, with more = denoting subheadings. E.g. =Heading=, ==Sub-Heading==, etc. List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles.","title":"Other formatting notes"},{"location":"Scala/sbt/","text":"SBT Links \u00b6 SBT Home Page Scala school's SBT page SBT: The Missing Tutorial Create a New Project \u00b6 $ sbt new sbt/scala-seed.g8 $ cd hello $ sbt ... > run > exit Giter8 templates Layout \u00b6 sbt uses the same directory structure as Maven for source files by default (all paths are relative to the base directory): src/ main/ resources/ scala/
java/
test/ resources scala/ java/ Other directories in src/ will be ignored. Additionally, all hidden directories will be ignored. Source code can be placed in the project\u2019s base directory as hello/app.scala , which may be for small projects, though for normal projects people tend to keep the projects in the src/main/ directory to keep things neat. Build Definition \u00b6 The build definition goes in a file called build.sbt , located in the project\u2019s base directory. The \u201cbase directory\u201d is the directory containing the project. In addition to build.sbt , the project directory can contain .scala files that defines helper objects and one-off plugins. build.sbt project/ Dependencies.scala .gitignore (or equivalent for other version control systems) should contain: target/ As part of your build definition, specify the version of sbt that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. To do this, create a file named project/build.properties that specifies the sbt version as follows: sbt.version=1.0.2 A build definition is defined in build.sbt, and it consists of a set of projects (of type Project). Because the term project can be ambiguous, we often call it a subproject. lazy val root = ( project in file ( \".\" )) . settings ( name := \"Hello\" , scalaVersion := \"2.12.3\" ) Each subproject is configured by key-value pairs. build.sbt may also be interspersed with vals, lazy vals, and defs. Top-level objects and classes are not allowed in build.sbt . Those should go in the project/ directory as Scala source files. There are three flavors of key: SettingKey[T]: a key for a value computed once (the value is computed when loading the subproject, and kept around). TaskKey[T]: a key for a value, called a task, that has to be recomputed each time, potentially with side effects. InputKey[T]: a key for a task that has command line arguments as input. Check out Input Tasks for more details. Built-in Keys \u00b6 The built-in keys are just fields in an object called Keys. A build.sbt implicitly has an import sbt.Keys._ , so sbt.Keys.name can be referred to as name. Adding Library Dependencies \u00b6 To depend on third-party libraries, there are two options. The first is to drop jars in lib/ (unmanaged dependencies) and the other is to add managed dependencies, which will look like this in build.sbt : val derby = \"org.apache.derby\" % \"derby\" % \"10.4.1.3\" lazy val commonSettings = Seq ( organization := \"com.example\" , version := \"0.1.0-SNAPSHOT\" , scalaVersion := \"2.12.3\" ) lazy val root = ( project in file ( \".\" )) . settings ( commonSettings , name := \"Hello\" , libraryDependencies += derby ) The libraryDependencies key involves two complexities: += rather than := , and the % method. += appends to the key\u2019s old value rather than replacing it. The % method is used to construct an Ivy module ID from strings.","title":"Sbt"},{"location":"Scala/sbt/#sbt-links","text":"SBT Home Page Scala school's SBT page SBT: The Missing Tutorial","title":"SBT Links"},{"location":"Scala/sbt/#create-a-new-project","text":"$ sbt new sbt/scala-seed.g8 $ cd hello $ sbt ... > run > exit Giter8 templates","title":"Create a New Project"},{"location":"Scala/sbt/#layout","text":"sbt uses the same directory structure as Maven for source files by default (all paths are relative to the base directory): src/ main/ resources/ scala/
java/
test/ resources scala/ java/ Other directories in src/ will be ignored. Additionally, all hidden directories will be ignored. Source code can be placed in the project\u2019s base directory as hello/app.scala , which may be for small projects, though for normal projects people tend to keep the projects in the src/main/ directory to keep things neat.","title":"Layout"},{"location":"Scala/sbt/#build-definition","text":"The build definition goes in a file called build.sbt , located in the project\u2019s base directory. The \u201cbase directory\u201d is the directory containing the project. In addition to build.sbt , the project directory can contain .scala files that defines helper objects and one-off plugins. build.sbt project/ Dependencies.scala .gitignore (or equivalent for other version control systems) should contain: target/ As part of your build definition, specify the version of sbt that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. To do this, create a file named project/build.properties that specifies the sbt version as follows: sbt.version=1.0.2 A build definition is defined in build.sbt, and it consists of a set of projects (of type Project). Because the term project can be ambiguous, we often call it a subproject. lazy val root = ( project in file ( \".\" )) . settings ( name := \"Hello\" , scalaVersion := \"2.12.3\" ) Each subproject is configured by key-value pairs. build.sbt may also be interspersed with vals, lazy vals, and defs. Top-level objects and classes are not allowed in build.sbt . Those should go in the project/ directory as Scala source files. There are three flavors of key: SettingKey[T]: a key for a value computed once (the value is computed when loading the subproject, and kept around). TaskKey[T]: a key for a value, called a task, that has to be recomputed each time, potentially with side effects. InputKey[T]: a key for a task that has command line arguments as input. Check out Input Tasks for more details.","title":"Build Definition"},{"location":"Scala/sbt/#built-in-keys","text":"The built-in keys are just fields in an object called Keys. A build.sbt implicitly has an import sbt.Keys._ , so sbt.Keys.name can be referred to as name.","title":"Built-in Keys"},{"location":"Scala/sbt/#adding-library-dependencies","text":"To depend on third-party libraries, there are two options. The first is to drop jars in lib/ (unmanaged dependencies) and the other is to add managed dependencies, which will look like this in build.sbt : val derby = \"org.apache.derby\" % \"derby\" % \"10.4.1.3\" lazy val commonSettings = Seq ( organization := \"com.example\" , version := \"0.1.0-SNAPSHOT\" , scalaVersion := \"2.12.3\" ) lazy val root = ( project in file ( \".\" )) . settings ( commonSettings , name := \"Hello\" , libraryDependencies += derby ) The libraryDependencies key involves two complexities: += rather than := , and the % method. += appends to the key\u2019s old value rather than replacing it. The % method is used to construct an Ivy module ID from strings.","title":"Adding Library Dependencies"},{"location":"Search/ElasticSearch/","text":"Cheatsheets \u00b6 Jolicode Development URLs \u00b6 Kibana (port 5601) Sense ElasticSearch (port 9200) INSTALL \u00b6 Install curl Install Java Download ElasticSearch Optionally change the cluster.name in the elasticsearch.yml configuration cd elasticsearch- ./bin/elasticsearch -d # or on Windows # bin\\elasticsearch.bat curl 'http://localhost:9200/?pretty' Install Kibana Open config/kibana.yml in an editor Set the elasticsearch.url to point at your Elasticsearch instance Run ./bin/kibana (orbin\\kibana.bat on Windows) Point your browser at http://localhost:5601 Install Sense ./bin/kibana plugin --install elastic/sense On Windows: bin \\k ibana.bat plugin --install elastic/sense Then go to http://localhost:5601/app/sense CURL \u00b6 curl -X '://:/?' -d '' verb is GET, POST, PUT, HEAD, or DELETE Examples \u00b6 curl -XGET 'http://localhost:9200/_count?pretty' -d '{ \"query\": { \"match_all\": {} }}' curl -XGET .us-west-2.es.amazonaws.com curl -XGET 'https://.us-west-2.es.amazonaws.com/_count?pretty' -d '{ \"query\": { \"match_all\": {} } }' curl -XPUT https://.us-west-2.es.amazonaws.com/movies/movie/tt0116996 -d '{\"directors\" : [\"Tim Burton\"],\"genres\" : [\"Comedy\",\"Sci-Fi\"], \"plot\": \"The Earth is invaded by Martians with irresistible weapons and a cruel sense of humor.\", \"title\" : \"Mars Attacks!\", \"actors\" :[\"Jack Nicholson\",\"Pierce Brosnan\",\"Sarah Jessica Parker\"], \"year\" : 1996}' Sense \u00b6 Sense syntax is similar to curl: Index a document PUT index/type/1 { \"body\": \"here\" } and retrieve it GET index/type/1 PLUGINS \u00b6 URL pattern http://yournode:9200/_plugin/ On Debian, the script is in: /usr/share/elasticsearch/bin/plugin . Install various plugins ./bin/plugin --install mobz/elasticsearch-head ./bin/plugin --install lmenezes/elasticsearch-kopf/1.2 ./bin/plugin --install elasticsearch/marvel/latest Remove a plugin ./bin/plugin --remove List installed plugins ./bin/plugin --list GET /_nodes?plugin=true Elasticsearch monitoring and management plugins Head Head elasticsearch/bin/plugin -install mobz/elasticsearch-head open http://localhost:9200/_plugin/head elastichq.org BigDesk Live charts and statistics for elasticsearch cluster: BigDesk Kopf Kopf ./bin/plugin --install lmenezes/elasticsearch-kopf/1.2` Marvel ./bin/plugin --install elasticsearch/marvel/latest Integrations (CMS, import/export, hadoop...) \u00b6 Integrations Aspire Aspire Aspire is a framework and libraries of extensible components designed to enable creation of solutions to acquire data from one or more content repositories (such as file systems, relational databases, cloud storage, or content management systems), extract metadata and text from the documents, analyze, modify and enhance the content and metadata if needed, and then publish each document, together with its metadata, to a search engine or other target application Docs Integration with Hadoop Integration with Hadoop Bulk loading for elastic search http://infochimps.com Integration with Spring Spring Data WordPress Wordpress TOOLS \u00b6 BI platforms that can use ES as an analytics engine: Kibana Grafana BIRT Birt Birt Adminer Adminer.org Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: WAMP Mongolastic A tool that migrates data from MongoDB to Elasticsearch and vice versa Mongolastic Elasticsearch-exporter Elasticsearch-exporter Code Examples - developing a Web UI for ES \u00b6 Sitepoint CottageLabs scrutmydocs.org qbox.io Java API \u00b6 Java clients elasticsearch tutorial elasticsearchfr/ IBM dzone BASICS \u00b6 An Elasticsearch cluster can contain multiple indices, which in turn contain multiple types. These types hold multiple documents, and each document has multiple fields. Explore (using Sense) \u00b6 GET _stats/ # List indices GET /_cat/indices/ GET /_cat/indices/my_ind* # Get info about one index GET /twitter GET /my_index_nr_1*/_settings?pretty or ?v GET /twitter/_settings,_mappings The available features are _settings, _mappings, _warmers and _aliases # cluster GET /_nodes # insert data PUT my_index/user/1 { \"first_name\": \"John\", \"last_name\": \"Smith\", \"date_of_birth\": \"1970-10-24\" } #search GET my_index/_search GET _count?pretty # Data schema GET my_index/_mapping INSERT DOCUMENTS \u00b6 PUT /index/type/ID PUT /megacorp/employee/1 { \"first_name\" : \"John\", \"last_name\" : \"Smith\", \"age\" : 25, \"about\" : \"I love to go rock climbing\", \"interests\": [ \"sports\", \"music\" ]} PUT /megacorp/employee/2 { \"first_name\" : \"Jane\", \"last_name\" : \"Smith\", \"age\" : 32, \"about\" : \"I like to collect rock albums\", \"interests\": [ \"music\" ]} GET /megacorp/employee/1 Field names can be any valid string, but may not include periods. Every document in Elasticsearch has a version number. Every time a change is made to a document (including deleting it), the _version number is incremented. Optimistic concurrency control PUT /website/blog/1?version=1 { \"title\": \"My first blog entry\", \"text\": \"Starting to get the hang of this...\"} We want this update to succeed only if the current _version of this document in our index is version 1 External version: PUT /website/blog/2?version=5&version_type=external { \"title\": \"My first external blog entry\", \"text\": \"Starting to get the hang of this...\"} INSERT DOCUMENTS - AUTOGENERATED IDS \u00b6 POST /website/blog/ { \"title\": \"My second blog entry\", \"text\": \"Still trying this out...\", \"date\": \"2014/01/01\" } Response: { \"_index\": \"website\", \"_type\": \"blog\", \"_id\": \"AVFgSgVHUP18jI2wRx0w\", \"_version\": 1, \"created\": true } # creating an entirely new document and not overwriting an existing one PUT /website/blog/123?op_type=create { ... } PUT /website/blog/123/_create { ... } RETRIEVE DOCUMENTS \u00b6 GET /website/blog/123 # optional ?pretty { \"_index\" : \"website\", \"_type\" : \"blog\", \"_id\" : \"123\", \"_version\" : 1, \"found\" : true, \"_source\" : { \"title\": \"My first blog entry\", \"text\": \"Just trying this out...\", \"date\": \"2014/01/01\" }} # Contains just the fields that we requested GET /website/blog/123?_source=title,text # Just get the original doc GET /website/blog/123/_source # check if doc exists -- HTTP 200 or 404 curl -i -XHEAD http://localhost:9200/website/blog/123 # Note: HEAD/exists requests do not work in Sense # because they only return HTTP headers, not # a JSON body # multiple docs at once GET /website/blog/_mget { \"ids\" : [ \"2\", \"1\" ]} UPDATE \u00b6 Documents in Elasticsearch are immutable; we cannot change them. Instead, if we need to update an existing document, we reindex or replace it # Accepts a partial document as the doc parameter, which just gets merged with the existing document. POST /website/blog/1/_update { \"doc\" : { \"tags\" : [ \"testing\" ], \"views\": 0 }} # Script POST /website/blog/1/_update { \"script\" : \"ctx._source.views+=1\"} # script with parameters POST /website/blog/1/_update { \"script\" : \"ctx._source.tags+=new_tag\", \"params\" : { \"new_tag\" : \"search\" }} # upsert POST/website/pageviews/1/_update {\"script\":\"ctx._source.views+=1\",\"upsert\":{\"views\":1}} DELETE \u00b6 DELETE /website/blog/123 # delete doc based on its contents POST /website/blog/1/_update { \"script\" : \"ctx.op = ctx._source.views == count ? 'delete' : 'none'\", \"params\" : { \"count\": 1 }} BULK \u00b6 POST /_bulk {\"delete\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\"}} {\"create\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\"}} # Create a document only if the document does not already exist {\"title\":\"My first blog post\"} {\"index\":{\"_index\":\"website\",\"_type\":\"blog\"}} {\"title\":\"My second blog post\"} {\"update\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\",\"_retry_on_conflict\":3}} {\"doc\":{\"title\":\"My updated blog post\"}} Bulk in the same index or index/type POST /website/_bulk {\"index\":{\"_type\":\"log\"}} {\"event\":\"User logged in\"} {\"index\":{\"_type\":\"blog\"}} {\"title\":\"My second blog post\"} Try around 5-15MB in size. SEARCH \u00b6 Every field in a document is indexed and can be queried. # Search for all employees in the megacorp index: GET /megacorp/employee/_search # Search for all employees in the megacorp index # who have \"Smith\" in the last_name field GET /megacorp/employee/_search?q=last_name:Smith # Same query as above, but using the Query DSL GET /megacorp/employee/_search { \"query\": { \"match\": { \"last_name\": \"smith\" } } } # SEARCH QUERY STRING GET /_all/tweet/_search?q=tweet:elasticsearch Don't forget to URL encode special characters e.g. +name:john +tweet:mary GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary The + prefix indicates conditions that must be satisfied for our query to match. Similarly a - prefix would indicate conditions that must not match. All conditions without a + or - are optional +name:(mary john) +date:>2014-09-10 +(aggregations geo) # last part searches _all QUERY DSL \u00b6 When used in filtering context, the query is said to be a \"non-scoring\" or \"filtering\" query. That is, the query simply asks the question: \"Does this document match?\". The answer is always a simple, binary yes|no. When used in a querying context, the query becomes a \"scoring\" query. # Find all employees whose `last_name` is Smith # and who are older than 30 GET /megacorp/employee/_search { \"query\" : { \"filtered\" : { \"filter\" : { \"range\" : { \"age\" : { \"gt\" : 30 } } }, \"query\" : { \"match\" : { \"last_name\" : \"smith\" } } } } } MATCH \u00b6 # Find all employees who enjoy \"rock\" or \"climbing\" GET /megacorp/employee/_search { \"query\" : { \"match\" : { \"about\" : \"rock climbing\" } } } The match query should be the standard query that you reach for whenever you want to query for a full-text or exact value in almost any field. If you run a match query against a full-text field, it will analyze the query string by using the correct analyzer for that field before executing the search If you use it on a field containing an exact value, such as a number, a date, a Boolean, or a not_analyzedstring field, then it will search for that exact value MATCH ON MULTIPLE FIELDS \u00b6 { \"multi_match\": { \"query\": \"full text search\", \"fields\": [ \"title\", \"body\" ] }} EXACT SEARCH \u00b6 # Find all employees who enjoy \"rock climbing\" GET /megacorp/employee/_search { \"query\" : { \"match_phrase\" : { \"about\" : \"rock climbing\" } } } # EXACT VALUES The term query is used to search by exact values, be they numbers, dates, Booleans, or not_analyzed exact-value string fields The terms query is the same as the term query, but allows you to specify multiple values to match. If the field contains any of the specified values, the document matches { \"terms\": { \"tag\": [ \"search\", \"full_text\", \"nosql\" ] }} # Compound Queries { \"bool\": { \"must\": { \"match\": { \"tweet\": \"elasticsearch\" }}, \"must_not\": { \"match\": { \"name\": \"mary\" }}, \"should\": { \"match\": { \"tweet\": \"full text\" }}, \"filter\": { \"range\": { \"age\" : { \"gt\" : 30 }} } } } # VALIDATE A QUERY GET /gb/tweet/_validate/query?explain { \"query\": { \"tweet\" : { \"match\" : \"really powerful\" } }} # understand why one particular document matched or, more important, why it didn\u2019t match GET /us/tweet/12/_explain { \"query\" : { \"bool\" : { \"filter\" : { \"term\" : { \"user_id\" : 2 }}, \"must\" : { \"match\" : { \"tweet\" : \"honeymoon\" }} } }} MULTIPLE INDICES OR TYPES \u00b6 # all documents all indices /_search /gb,us/_search Search all types in the gb and us indices /g ,u /_search Search all types in any indices beginning with g or beginning with u /gb/user/_search Search type user in the gb index /gb,us/user,tweet/_search Search types user and tweet in the gb and us indices /_all/user,tweet/_search Search types user and tweet in all indices PAGINATION \u00b6 GET /_search?size=5GET /_search?size=5&from=5 SORTING \u00b6 GET /_search { \"query\" : { \"bool\" : { \"filter\" : { \"term\" : { \"user_id\" : 1 }} } }, \"sort\": { \"date\": { \"order\": \"desc\" }}} For string sorting, use multi-field mapping: \"tweet\": { \"type\": \"string\", \"analyzer\": \"english\", \"fields\": { \"raw\": {\"type\": \"string\", \"index\": \"not_analyzed\" } }} The main tweet field is just the same as before: an analyzed full-text field. The new tweet.raw subfield is not_analyzed. then sort on the new field GET /_search { \"query\": { \"match\": { \"tweet\": \"elasticsearch\" } }, \"sort\": \"tweet.raw\"} HIGHLIGHTS \u00b6 # Find all employees who enjoy \"rock climbing\" - highlights # and highlight the matches GET /megacorp/employee/_search { \"query\" : { \"match_phrase\" : { \"about\" : \"rock climbing\" } }, \"highlight\": { \"fields\" : { \"about\" : {} } } } ANALYSIS \u00b6 An analyzer is really just a wrapper that combines three functions into a single package: * Character filters * Tokenizer * Token filters # See how text is analyzed GET /_analyze { \"analyzer\": \"standard\", \"text\": \"Text to analyze\"} # test analyzer GET /gb/_analyze { \"field\": \"tweet\", \"text\": \"Black-cats\"} MAPPINGS (schemas) \u00b6 Every type has its own mapping, or schema definition. A mapping defines the fields within a type, the datatype for each field, and how the field should be handled by Elasticsearch. A mapping is also used to configure metadata associated with the type. You can control dynamic nature of mappings Mapping (or schema definition) for the tweet type in the gb index GET /gb/_mapping/tweet Elasticsearch supports the following simple field types: * String: string * Whole number: byte, short, integer, long * Floating-point: float, double * Boolean: boolean * Date: date Fields of type string are, by default, considered to contain full text. That is, their value will be passed through an analyzer before being indexed, and a full-text query on the field will pass the query string through an analyzer before searching. The two most important mapping attributes for string fields are index and analyzer. The index attribute controls how the string will be indexed. It can contain one of three values: * analyzed First analyze the string and then index it. In other words, index this field as full text. * not_analyzed Index this field, so it is searchable, but index the value exactly as specified. Do not analyze it. * no Don\u2019t index this field at all. This field will not be searchable. If we want to map the field as an exact value, we need to set it to not_analyzed: { \"tag\": { \"type\": \"string\", \"index\": \"not_analyzed\" } } For analyzed string fields, use the analyzer attribute to specify which analyzer to apply both at search time and at index time. By default, Elasticsearch uses the standard analyzer, but you can change this by specifying one of the built-in analyzers, such as whitespace, simple, or english: { \"tweet\": { \"type\": \"string\", \"analyzer\": \"english\" } } # create a new index, specifying that the tweet field should use the english analyzer PUT /gb { \"mappings\": { \"tweet\" : { \"properties\" : { \"tweet\" : { \"type\" : \"string\", \"analyzer\": \"english\" }, \"date\" : { \"type\" : \"date\" }, \"name\" : { \"type\" : \"string\" }, \"user_id\" : { \"type\" : \"long\" } }}}} null, arrays, objects: see complex core fields Parent Child Relationships \u00b6 DELETE / test _i n dex PUT / test _i n dex { \"mappings\" : { \"parent_type\" : { \"properties\" : { \"num_prop\" : { \"type\" : \"integer\" }, \"str_prop\" : { \"type\" : \"string\" } } }, \"child_type\" : { \"_parent\" : { \"type\" : \"parent_type\" }, \"properties\" : { \"child_num\" : { \"type\" : \"integer\" }, \"child_str\" : { \"type\" : \"string\" } } } } } POST / test _i n dex/_bulk { \"index\" :{ \"_type\" : \"parent_type\" , \"_id\" : 1 }} { \"num_prop\" : 1 , \"str_prop\" : \"hello\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 1 , \"_parent\" : 1 }} { \"child_num\" : 11 , \"child_str\" : \"foo\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 2 , \"_parent\" : 1 }} { \"child_num\" : 12 , \"child_str\" : \"bar\" } { \"index\" :{ \"_type\" : \"parent_type\" , \"_id\" : 2 }} { \"num_prop\" : 2 , \"str_prop\" : \"goodbye\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 3 , \"_parent\" : 2 }} { \"child_num\" : 21 , \"child_str\" : \"baz\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/ 2 ?pare nt = 1 { \"child_num\" : 13 , \"child_str\" : \"bars\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/ 3 /_upda te ?pare nt = 2 { \"script\" : \"ctx._source.child_num+=1\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/_search { \"query\" : { \"term\" : { \"child_str\" : { \"value\" : \"foo\" } } } } POST / test _i n dex/pare nt _ t ype/_search { \"query\" : { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\" : { \"has_child\" : { \"type\" : \"child_type\" , \"filter\" : { \"term\" : { \"child_str\" : \"foo\" } } } } } } } AGGREGATES \u00b6 Aggregations and searches can span multiple indices # Calculate the most popular interests for all employees GET /megacorp/employee/_search { \"aggs\": { \"all_interests\": { \"terms\": { \"field\": \"interests\" } } } } # Calculate the most popular interests for # employees named \"Smith\" GET /megacorp/employee/_search { \"query\": { \"match\": { \"last_name\": \"smith\" } }, \"aggs\": { \"all_interests\": { \"terms\": { \"field\": \"interests\" } } } } # Calculate the average age of employee per interest - hierarchical aggregates GET /megacorp/employee/_search { \"aggs\" : { \"all_interests\" : { \"terms\" : { \"field\" : \"interests\" }, \"aggs\" : { \"avg_age\" : { \"avg\" : { \"field\" : \"age\" } } } } } } # requires in config/elasticsearch.yml # script.inline: true # script.indexed: true GET /tlo/contacts/_search { \"size\" : 0, \"query\": { \"constant_score\": { \"filter\": { \"terms\": { \"version\": [ \"20160301\", \"20160401\" ] } } } }, \"aggs\": { \"counts\": { \"cardinality\": { \"script\": \"doc['first_name'].value + ' ' + doc['last_name'].value + ' ' + doc['company'].value\", \"missing\": \"N/A\" } } } } INDEX MANAGEMENT \u00b6 By default, indices are assigned five primary shards. The number of primary shards can be set only when an index is created and never changed # Add an index PUT /blogs { \"settings\" : { \"number_of_shards\" : 3, \"number_of_replicas\" : 1 }} PUT /blogs/_settings { \"number_of_replicas\" : 2} ElasticSearch Shards should be 50 GB or less in size. Use aliases to shelter the underlying index (or indices) and allow index swapping CLUSTER MANAGEMENT \u00b6 GET /_cluster/health CONFIGURATION \u00b6 config directory yaml file Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache Prefer not to allocate 30GB !! --> uncompressed pointers Never let the JVM swap bootstrap.mlockall = true Keep the JVM defaults Do not use G1GC alternative garbage collector cluster.name: All nodes in the cluster must have the same cluster name node.name: ./bin/elasticsearch --node.name=`hostname` to override the configuration file HTTP port: 9200 and successors Transport : 9300 (internal communications) Discovery \u00b6 AWS plugin available --> also include integration with S3 (snapshot to S3) AWS: multi-AZ is OK but replication across far data centers is not recommended See: resiliency Sites plugins -- kopf / head / paramedic / bigdesk / kibana - contain static web content (JS, HTML....) Install plugins on ALL machines of the cluster To install, ./bin/plugin install marvel-agent ./bin/plugin remove marvel-agent One type per index is recommended, except for parent child / nested indexes. index size optimization: - can disable _source and _all (the index that captures every field - not needed unless the top search bar changes) - by default, Kibana will search _all data types: string, number, bool, datetime, binary, array, object, geo_point, geo_shape, ip, multifield binary should be base64 encoded before storage MAINTENANCE \u00b6 Steps to restore elastic search data: Stop elastic search Extract the zip file (dump file) Start elastic search Reload elastic search The commands to do the above are as below: systemctl stop elasticsearch extract gz file to destination path systemctl start elasticsearch systemctl daemon-reload elasticsearch","title":"ElasticSearch Cheatsheet"},{"location":"Search/ElasticSearch/#cheatsheets","text":"Jolicode","title":"Cheatsheets"},{"location":"Search/ElasticSearch/#development-urls","text":"Kibana (port 5601) Sense ElasticSearch (port 9200)","title":"Development URLs"},{"location":"Search/ElasticSearch/#install","text":"Install curl Install Java Download ElasticSearch Optionally change the cluster.name in the elasticsearch.yml configuration cd elasticsearch- ./bin/elasticsearch -d # or on Windows # bin\\elasticsearch.bat curl 'http://localhost:9200/?pretty' Install Kibana Open config/kibana.yml in an editor Set the elasticsearch.url to point at your Elasticsearch instance Run ./bin/kibana (orbin\\kibana.bat on Windows) Point your browser at http://localhost:5601 Install Sense ./bin/kibana plugin --install elastic/sense On Windows: bin \\k ibana.bat plugin --install elastic/sense Then go to http://localhost:5601/app/sense","title":"INSTALL"},{"location":"Search/ElasticSearch/#curl","text":"curl -X '://:/?' -d '' verb is GET, POST, PUT, HEAD, or DELETE","title":"CURL"},{"location":"Search/ElasticSearch/#examples","text":"curl -XGET 'http://localhost:9200/_count?pretty' -d '{ \"query\": { \"match_all\": {} }}' curl -XGET .us-west-2.es.amazonaws.com curl -XGET 'https://.us-west-2.es.amazonaws.com/_count?pretty' -d '{ \"query\": { \"match_all\": {} } }' curl -XPUT https://.us-west-2.es.amazonaws.com/movies/movie/tt0116996 -d '{\"directors\" : [\"Tim Burton\"],\"genres\" : [\"Comedy\",\"Sci-Fi\"], \"plot\": \"The Earth is invaded by Martians with irresistible weapons and a cruel sense of humor.\", \"title\" : \"Mars Attacks!\", \"actors\" :[\"Jack Nicholson\",\"Pierce Brosnan\",\"Sarah Jessica Parker\"], \"year\" : 1996}'","title":"Examples"},{"location":"Search/ElasticSearch/#sense","text":"Sense syntax is similar to curl: Index a document PUT index/type/1 { \"body\": \"here\" } and retrieve it GET index/type/1","title":"Sense"},{"location":"Search/ElasticSearch/#plugins","text":"URL pattern http://yournode:9200/_plugin/ On Debian, the script is in: /usr/share/elasticsearch/bin/plugin . Install various plugins ./bin/plugin --install mobz/elasticsearch-head ./bin/plugin --install lmenezes/elasticsearch-kopf/1.2 ./bin/plugin --install elasticsearch/marvel/latest Remove a plugin ./bin/plugin --remove List installed plugins ./bin/plugin --list GET /_nodes?plugin=true Elasticsearch monitoring and management plugins Head Head elasticsearch/bin/plugin -install mobz/elasticsearch-head open http://localhost:9200/_plugin/head elastichq.org BigDesk Live charts and statistics for elasticsearch cluster: BigDesk Kopf Kopf ./bin/plugin --install lmenezes/elasticsearch-kopf/1.2` Marvel ./bin/plugin --install elasticsearch/marvel/latest","title":"PLUGINS"},{"location":"Search/ElasticSearch/#integrations-cms-importexport-hadoop","text":"Integrations Aspire Aspire Aspire is a framework and libraries of extensible components designed to enable creation of solutions to acquire data from one or more content repositories (such as file systems, relational databases, cloud storage, or content management systems), extract metadata and text from the documents, analyze, modify and enhance the content and metadata if needed, and then publish each document, together with its metadata, to a search engine or other target application Docs Integration with Hadoop Integration with Hadoop Bulk loading for elastic search http://infochimps.com Integration with Spring Spring Data WordPress Wordpress","title":"Integrations (CMS, import/export, hadoop...)"},{"location":"Search/ElasticSearch/#tools","text":"BI platforms that can use ES as an analytics engine: Kibana Grafana BIRT Birt Birt Adminer Adminer.org Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: WAMP Mongolastic A tool that migrates data from MongoDB to Elasticsearch and vice versa Mongolastic Elasticsearch-exporter Elasticsearch-exporter","title":"TOOLS"},{"location":"Search/ElasticSearch/#code-examples---developing-a-web-ui-for-es","text":"Sitepoint CottageLabs scrutmydocs.org qbox.io","title":"Code Examples - developing a Web UI for ES"},{"location":"Search/ElasticSearch/#java-api","text":"Java clients elasticsearch tutorial elasticsearchfr/ IBM dzone","title":"Java API"},{"location":"Search/ElasticSearch/#basics","text":"An Elasticsearch cluster can contain multiple indices, which in turn contain multiple types. These types hold multiple documents, and each document has multiple fields.","title":"BASICS"},{"location":"Search/ElasticSearch/#explore-using-sense","text":"GET _stats/ # List indices GET /_cat/indices/ GET /_cat/indices/my_ind* # Get info about one index GET /twitter GET /my_index_nr_1*/_settings?pretty or ?v GET /twitter/_settings,_mappings The available features are _settings, _mappings, _warmers and _aliases # cluster GET /_nodes # insert data PUT my_index/user/1 { \"first_name\": \"John\", \"last_name\": \"Smith\", \"date_of_birth\": \"1970-10-24\" } #search GET my_index/_search GET _count?pretty # Data schema GET my_index/_mapping","title":"Explore (using Sense)"},{"location":"Search/ElasticSearch/#insert-documents","text":"PUT /index/type/ID PUT /megacorp/employee/1 { \"first_name\" : \"John\", \"last_name\" : \"Smith\", \"age\" : 25, \"about\" : \"I love to go rock climbing\", \"interests\": [ \"sports\", \"music\" ]} PUT /megacorp/employee/2 { \"first_name\" : \"Jane\", \"last_name\" : \"Smith\", \"age\" : 32, \"about\" : \"I like to collect rock albums\", \"interests\": [ \"music\" ]} GET /megacorp/employee/1 Field names can be any valid string, but may not include periods. Every document in Elasticsearch has a version number. Every time a change is made to a document (including deleting it), the _version number is incremented. Optimistic concurrency control PUT /website/blog/1?version=1 { \"title\": \"My first blog entry\", \"text\": \"Starting to get the hang of this...\"} We want this update to succeed only if the current _version of this document in our index is version 1 External version: PUT /website/blog/2?version=5&version_type=external { \"title\": \"My first external blog entry\", \"text\": \"Starting to get the hang of this...\"}","title":"INSERT DOCUMENTS"},{"location":"Search/ElasticSearch/#insert-documents---autogenerated-ids","text":"POST /website/blog/ { \"title\": \"My second blog entry\", \"text\": \"Still trying this out...\", \"date\": \"2014/01/01\" } Response: { \"_index\": \"website\", \"_type\": \"blog\", \"_id\": \"AVFgSgVHUP18jI2wRx0w\", \"_version\": 1, \"created\": true } # creating an entirely new document and not overwriting an existing one PUT /website/blog/123?op_type=create { ... } PUT /website/blog/123/_create { ... }","title":"INSERT DOCUMENTS - AUTOGENERATED IDS"},{"location":"Search/ElasticSearch/#retrieve-documents","text":"GET /website/blog/123 # optional ?pretty { \"_index\" : \"website\", \"_type\" : \"blog\", \"_id\" : \"123\", \"_version\" : 1, \"found\" : true, \"_source\" : { \"title\": \"My first blog entry\", \"text\": \"Just trying this out...\", \"date\": \"2014/01/01\" }} # Contains just the fields that we requested GET /website/blog/123?_source=title,text # Just get the original doc GET /website/blog/123/_source # check if doc exists -- HTTP 200 or 404 curl -i -XHEAD http://localhost:9200/website/blog/123 # Note: HEAD/exists requests do not work in Sense # because they only return HTTP headers, not # a JSON body # multiple docs at once GET /website/blog/_mget { \"ids\" : [ \"2\", \"1\" ]}","title":"RETRIEVE DOCUMENTS"},{"location":"Search/ElasticSearch/#update","text":"Documents in Elasticsearch are immutable; we cannot change them. Instead, if we need to update an existing document, we reindex or replace it # Accepts a partial document as the doc parameter, which just gets merged with the existing document. POST /website/blog/1/_update { \"doc\" : { \"tags\" : [ \"testing\" ], \"views\": 0 }} # Script POST /website/blog/1/_update { \"script\" : \"ctx._source.views+=1\"} # script with parameters POST /website/blog/1/_update { \"script\" : \"ctx._source.tags+=new_tag\", \"params\" : { \"new_tag\" : \"search\" }} # upsert POST/website/pageviews/1/_update {\"script\":\"ctx._source.views+=1\",\"upsert\":{\"views\":1}}","title":"UPDATE"},{"location":"Search/ElasticSearch/#delete","text":"DELETE /website/blog/123 # delete doc based on its contents POST /website/blog/1/_update { \"script\" : \"ctx.op = ctx._source.views == count ? 'delete' : 'none'\", \"params\" : { \"count\": 1 }}","title":"DELETE"},{"location":"Search/ElasticSearch/#bulk","text":"POST /_bulk {\"delete\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\"}} {\"create\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\"}} # Create a document only if the document does not already exist {\"title\":\"My first blog post\"} {\"index\":{\"_index\":\"website\",\"_type\":\"blog\"}} {\"title\":\"My second blog post\"} {\"update\":{\"_index\":\"website\",\"_type\":\"blog\",\"_id\":\"123\",\"_retry_on_conflict\":3}} {\"doc\":{\"title\":\"My updated blog post\"}} Bulk in the same index or index/type POST /website/_bulk {\"index\":{\"_type\":\"log\"}} {\"event\":\"User logged in\"} {\"index\":{\"_type\":\"blog\"}} {\"title\":\"My second blog post\"} Try around 5-15MB in size.","title":"BULK"},{"location":"Search/ElasticSearch/#search","text":"Every field in a document is indexed and can be queried. # Search for all employees in the megacorp index: GET /megacorp/employee/_search # Search for all employees in the megacorp index # who have \"Smith\" in the last_name field GET /megacorp/employee/_search?q=last_name:Smith # Same query as above, but using the Query DSL GET /megacorp/employee/_search { \"query\": { \"match\": { \"last_name\": \"smith\" } } } # SEARCH QUERY STRING GET /_all/tweet/_search?q=tweet:elasticsearch Don't forget to URL encode special characters e.g. +name:john +tweet:mary GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary The + prefix indicates conditions that must be satisfied for our query to match. Similarly a - prefix would indicate conditions that must not match. All conditions without a + or - are optional +name:(mary john) +date:>2014-09-10 +(aggregations geo) # last part searches _all","title":"SEARCH"},{"location":"Search/ElasticSearch/#query-dsl","text":"When used in filtering context, the query is said to be a \"non-scoring\" or \"filtering\" query. That is, the query simply asks the question: \"Does this document match?\". The answer is always a simple, binary yes|no. When used in a querying context, the query becomes a \"scoring\" query. # Find all employees whose `last_name` is Smith # and who are older than 30 GET /megacorp/employee/_search { \"query\" : { \"filtered\" : { \"filter\" : { \"range\" : { \"age\" : { \"gt\" : 30 } } }, \"query\" : { \"match\" : { \"last_name\" : \"smith\" } } } } }","title":"QUERY DSL"},{"location":"Search/ElasticSearch/#match","text":"# Find all employees who enjoy \"rock\" or \"climbing\" GET /megacorp/employee/_search { \"query\" : { \"match\" : { \"about\" : \"rock climbing\" } } } The match query should be the standard query that you reach for whenever you want to query for a full-text or exact value in almost any field. If you run a match query against a full-text field, it will analyze the query string by using the correct analyzer for that field before executing the search If you use it on a field containing an exact value, such as a number, a date, a Boolean, or a not_analyzedstring field, then it will search for that exact value","title":"MATCH"},{"location":"Search/ElasticSearch/#match-on-multiple-fields","text":"{ \"multi_match\": { \"query\": \"full text search\", \"fields\": [ \"title\", \"body\" ] }}","title":"MATCH ON MULTIPLE FIELDS"},{"location":"Search/ElasticSearch/#exact-search","text":"# Find all employees who enjoy \"rock climbing\" GET /megacorp/employee/_search { \"query\" : { \"match_phrase\" : { \"about\" : \"rock climbing\" } } } # EXACT VALUES The term query is used to search by exact values, be they numbers, dates, Booleans, or not_analyzed exact-value string fields The terms query is the same as the term query, but allows you to specify multiple values to match. If the field contains any of the specified values, the document matches { \"terms\": { \"tag\": [ \"search\", \"full_text\", \"nosql\" ] }} # Compound Queries { \"bool\": { \"must\": { \"match\": { \"tweet\": \"elasticsearch\" }}, \"must_not\": { \"match\": { \"name\": \"mary\" }}, \"should\": { \"match\": { \"tweet\": \"full text\" }}, \"filter\": { \"range\": { \"age\" : { \"gt\" : 30 }} } } } # VALIDATE A QUERY GET /gb/tweet/_validate/query?explain { \"query\": { \"tweet\" : { \"match\" : \"really powerful\" } }} # understand why one particular document matched or, more important, why it didn\u2019t match GET /us/tweet/12/_explain { \"query\" : { \"bool\" : { \"filter\" : { \"term\" : { \"user_id\" : 2 }}, \"must\" : { \"match\" : { \"tweet\" : \"honeymoon\" }} } }}","title":"EXACT SEARCH"},{"location":"Search/ElasticSearch/#multiple-indices-or-types","text":"# all documents all indices /_search /gb,us/_search Search all types in the gb and us indices /g ,u /_search Search all types in any indices beginning with g or beginning with u /gb/user/_search Search type user in the gb index /gb,us/user,tweet/_search Search types user and tweet in the gb and us indices /_all/user,tweet/_search Search types user and tweet in all indices","title":"MULTIPLE INDICES OR TYPES"},{"location":"Search/ElasticSearch/#pagination","text":"GET /_search?size=5GET /_search?size=5&from=5","title":"PAGINATION"},{"location":"Search/ElasticSearch/#sorting","text":"GET /_search { \"query\" : { \"bool\" : { \"filter\" : { \"term\" : { \"user_id\" : 1 }} } }, \"sort\": { \"date\": { \"order\": \"desc\" }}} For string sorting, use multi-field mapping: \"tweet\": { \"type\": \"string\", \"analyzer\": \"english\", \"fields\": { \"raw\": {\"type\": \"string\", \"index\": \"not_analyzed\" } }} The main tweet field is just the same as before: an analyzed full-text field. The new tweet.raw subfield is not_analyzed. then sort on the new field GET /_search { \"query\": { \"match\": { \"tweet\": \"elasticsearch\" } }, \"sort\": \"tweet.raw\"}","title":"SORTING"},{"location":"Search/ElasticSearch/#highlights","text":"# Find all employees who enjoy \"rock climbing\" - highlights # and highlight the matches GET /megacorp/employee/_search { \"query\" : { \"match_phrase\" : { \"about\" : \"rock climbing\" } }, \"highlight\": { \"fields\" : { \"about\" : {} } } }","title":"HIGHLIGHTS"},{"location":"Search/ElasticSearch/#analysis","text":"An analyzer is really just a wrapper that combines three functions into a single package: * Character filters * Tokenizer * Token filters # See how text is analyzed GET /_analyze { \"analyzer\": \"standard\", \"text\": \"Text to analyze\"} # test analyzer GET /gb/_analyze { \"field\": \"tweet\", \"text\": \"Black-cats\"}","title":"ANALYSIS"},{"location":"Search/ElasticSearch/#mappings-schemas","text":"Every type has its own mapping, or schema definition. A mapping defines the fields within a type, the datatype for each field, and how the field should be handled by Elasticsearch. A mapping is also used to configure metadata associated with the type. You can control dynamic nature of mappings Mapping (or schema definition) for the tweet type in the gb index GET /gb/_mapping/tweet Elasticsearch supports the following simple field types: * String: string * Whole number: byte, short, integer, long * Floating-point: float, double * Boolean: boolean * Date: date Fields of type string are, by default, considered to contain full text. That is, their value will be passed through an analyzer before being indexed, and a full-text query on the field will pass the query string through an analyzer before searching. The two most important mapping attributes for string fields are index and analyzer. The index attribute controls how the string will be indexed. It can contain one of three values: * analyzed First analyze the string and then index it. In other words, index this field as full text. * not_analyzed Index this field, so it is searchable, but index the value exactly as specified. Do not analyze it. * no Don\u2019t index this field at all. This field will not be searchable. If we want to map the field as an exact value, we need to set it to not_analyzed: { \"tag\": { \"type\": \"string\", \"index\": \"not_analyzed\" } } For analyzed string fields, use the analyzer attribute to specify which analyzer to apply both at search time and at index time. By default, Elasticsearch uses the standard analyzer, but you can change this by specifying one of the built-in analyzers, such as whitespace, simple, or english: { \"tweet\": { \"type\": \"string\", \"analyzer\": \"english\" } } # create a new index, specifying that the tweet field should use the english analyzer PUT /gb { \"mappings\": { \"tweet\" : { \"properties\" : { \"tweet\" : { \"type\" : \"string\", \"analyzer\": \"english\" }, \"date\" : { \"type\" : \"date\" }, \"name\" : { \"type\" : \"string\" }, \"user_id\" : { \"type\" : \"long\" } }}}} null, arrays, objects: see complex core fields","title":"MAPPINGS (schemas)"},{"location":"Search/ElasticSearch/#parent-child-relationships","text":"DELETE / test _i n dex PUT / test _i n dex { \"mappings\" : { \"parent_type\" : { \"properties\" : { \"num_prop\" : { \"type\" : \"integer\" }, \"str_prop\" : { \"type\" : \"string\" } } }, \"child_type\" : { \"_parent\" : { \"type\" : \"parent_type\" }, \"properties\" : { \"child_num\" : { \"type\" : \"integer\" }, \"child_str\" : { \"type\" : \"string\" } } } } } POST / test _i n dex/_bulk { \"index\" :{ \"_type\" : \"parent_type\" , \"_id\" : 1 }} { \"num_prop\" : 1 , \"str_prop\" : \"hello\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 1 , \"_parent\" : 1 }} { \"child_num\" : 11 , \"child_str\" : \"foo\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 2 , \"_parent\" : 1 }} { \"child_num\" : 12 , \"child_str\" : \"bar\" } { \"index\" :{ \"_type\" : \"parent_type\" , \"_id\" : 2 }} { \"num_prop\" : 2 , \"str_prop\" : \"goodbye\" } { \"index\" :{ \"_type\" : \"child_type\" , \"_id\" : 3 , \"_parent\" : 2 }} { \"child_num\" : 21 , \"child_str\" : \"baz\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/ 2 ?pare nt = 1 { \"child_num\" : 13 , \"child_str\" : \"bars\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/ 3 /_upda te ?pare nt = 2 { \"script\" : \"ctx._source.child_num+=1\" } POST / test _i n dex/child_ t ype/_search POST / test _i n dex/child_ t ype/_search { \"query\" : { \"term\" : { \"child_str\" : { \"value\" : \"foo\" } } } } POST / test _i n dex/pare nt _ t ype/_search { \"query\" : { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\" : { \"has_child\" : { \"type\" : \"child_type\" , \"filter\" : { \"term\" : { \"child_str\" : \"foo\" } } } } } } }","title":"Parent Child Relationships"},{"location":"Search/ElasticSearch/#aggregates","text":"Aggregations and searches can span multiple indices # Calculate the most popular interests for all employees GET /megacorp/employee/_search { \"aggs\": { \"all_interests\": { \"terms\": { \"field\": \"interests\" } } } } # Calculate the most popular interests for # employees named \"Smith\" GET /megacorp/employee/_search { \"query\": { \"match\": { \"last_name\": \"smith\" } }, \"aggs\": { \"all_interests\": { \"terms\": { \"field\": \"interests\" } } } } # Calculate the average age of employee per interest - hierarchical aggregates GET /megacorp/employee/_search { \"aggs\" : { \"all_interests\" : { \"terms\" : { \"field\" : \"interests\" }, \"aggs\" : { \"avg_age\" : { \"avg\" : { \"field\" : \"age\" } } } } } } # requires in config/elasticsearch.yml # script.inline: true # script.indexed: true GET /tlo/contacts/_search { \"size\" : 0, \"query\": { \"constant_score\": { \"filter\": { \"terms\": { \"version\": [ \"20160301\", \"20160401\" ] } } } }, \"aggs\": { \"counts\": { \"cardinality\": { \"script\": \"doc['first_name'].value + ' ' + doc['last_name'].value + ' ' + doc['company'].value\", \"missing\": \"N/A\" } } } }","title":"AGGREGATES"},{"location":"Search/ElasticSearch/#index-management","text":"By default, indices are assigned five primary shards. The number of primary shards can be set only when an index is created and never changed # Add an index PUT /blogs { \"settings\" : { \"number_of_shards\" : 3, \"number_of_replicas\" : 1 }} PUT /blogs/_settings { \"number_of_replicas\" : 2} ElasticSearch Shards should be 50 GB or less in size. Use aliases to shelter the underlying index (or indices) and allow index swapping","title":"INDEX MANAGEMENT"},{"location":"Search/ElasticSearch/#cluster-management","text":"GET /_cluster/health","title":"CLUSTER MANAGEMENT"},{"location":"Search/ElasticSearch/#configuration","text":"config directory yaml file Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache Prefer not to allocate 30GB !! --> uncompressed pointers Never let the JVM swap bootstrap.mlockall = true Keep the JVM defaults Do not use G1GC alternative garbage collector cluster.name: All nodes in the cluster must have the same cluster name node.name: ./bin/elasticsearch --node.name=`hostname` to override the configuration file HTTP port: 9200 and successors Transport : 9300 (internal communications)","title":"CONFIGURATION"},{"location":"Search/ElasticSearch/#discovery","text":"AWS plugin available --> also include integration with S3 (snapshot to S3) AWS: multi-AZ is OK but replication across far data centers is not recommended See: resiliency Sites plugins -- kopf / head / paramedic / bigdesk / kibana - contain static web content (JS, HTML....) Install plugins on ALL machines of the cluster To install, ./bin/plugin install marvel-agent ./bin/plugin remove marvel-agent One type per index is recommended, except for parent child / nested indexes. index size optimization: - can disable _source and _all (the index that captures every field - not needed unless the top search bar changes) - by default, Kibana will search _all data types: string, number, bool, datetime, binary, array, object, geo_point, geo_shape, ip, multifield binary should be base64 encoded before storage","title":"Discovery"},{"location":"Search/ElasticSearch/#maintenance","text":"Steps to restore elastic search data: Stop elastic search Extract the zip file (dump file) Start elastic search Reload elastic search The commands to do the above are as below: systemctl stop elasticsearch extract gz file to destination path systemctl start elasticsearch systemctl daemon-reload elasticsearch","title":"MAINTENANCE"},{"location":"Search/Logstash/","text":"LogStash \u00b6 Operations \u00b6 logstash -w 4 to set the number of worker threads Use path.data to distribute the data on multiple (EBS) disks Outputs \u00b6 MongoDB PagerDuty Nagios Graphite Ganglia StatsD Redis RabbitMQ output { elasticsearch { } # http://localhost:9200 } output { redis { host => \"redis.example.com\" data_type =>: \"list\" } } Output to file \u00b6 output { file { } } Filtering \u00b6 Use \"date\" for normalizing dates: filter { date{ timezone => \"America/Los_Angeles\" locale => \"en\" # English } geoip { source => \"clientip\" # will read from clientip field database => ... # use MaxMind's GeoLiteCity by default } useragent { } } Mutate a field \u00b6 filter { if [action] == \"login { mutate { remove_field => \"secret\" } } } Conditionals both in filter and outputs \u00b6 regexp =~ !~ output { if [loglevel] == \"ERROR\" } Interesting Plugins \u00b6 Stanford NLP library logstash plugin","title":"LogStash"},{"location":"Search/Logstash/#logstash","text":"","title":"LogStash"},{"location":"Search/Logstash/#operations","text":"logstash -w 4 to set the number of worker threads Use path.data to distribute the data on multiple (EBS) disks","title":"Operations"},{"location":"Search/Logstash/#outputs","text":"MongoDB PagerDuty Nagios Graphite Ganglia StatsD Redis RabbitMQ output { elasticsearch { } # http://localhost:9200 } output { redis { host => \"redis.example.com\" data_type =>: \"list\" } }","title":"Outputs"},{"location":"Search/Logstash/#output-to-file","text":"output { file { } }","title":"Output to file"},{"location":"Search/Logstash/#filtering","text":"Use \"date\" for normalizing dates: filter { date{ timezone => \"America/Los_Angeles\" locale => \"en\" # English } geoip { source => \"clientip\" # will read from clientip field database => ... # use MaxMind's GeoLiteCity by default } useragent { } }","title":"Filtering"},{"location":"Search/Logstash/#mutate-a-field","text":"filter { if [action] == \"login { mutate { remove_field => \"secret\" } } }","title":"Mutate a field"},{"location":"Search/Logstash/#conditionals-both-in-filter-and-outputs","text":"regexp =~ !~ output { if [loglevel] == \"ERROR\" }","title":"Conditionals both in filter and outputs"},{"location":"Search/Logstash/#interesting-plugins","text":"Stanford NLP library logstash plugin","title":"Interesting Plugins"},{"location":"Software_Development/Development_Tools/","text":"Communication / IM \u00b6 Slack Trillian / Pandion Skype, WeChat, Viber, Hangouts Wiki / Knowledge Base \u00b6 Confluence Evernote Project / Bug Tracking \u00b6 JIRA Bugzilla Mantis RedMine TFS Enterprise Architecture / UML \u00b6 Violet UML Editor Visio Rational Rose Terminals / SSH \u00b6 Putty MobaXterm mRemoteNG Remote Desktop Connection Manager Editors/ IDEs \u00b6 Comparison of integrated development environments Notepad++ Plugins Gedit Sublime Text Eclipse List of Eclipse-based software Visual Studio Visual Studio Code for Python Python Tools for Visual Studio PyDev PyCharm Anaconda Source Control \u00b6 SourceTree (Atlassian) GitHub TortoiseGit Code Quality \u00b6 SonarQube Phabricator Code Coverage Virtual Machines and Containers \u00b6 Oracle Virtualbox Docker Kubernetes SQL Tools \u00b6 MySQL Workbench HeidiSQL Aginity Workbench for Redshift (AWS) MongoDB tools \u00b6 RoboMongo MongoChef MongoDB Compass Data Quality \u00b6 DQ Analyzer (Attacama) Data Science \u00b6 Jupyter / IPython Rodeo Gephi AWS \u00b6 S3 Browser FastGlacier File Handling \u00b6 7zip FileZilla FolderSize Other \u00b6 Cygwin Log Tail Diff - WinMerge","title":"Development Tools"},{"location":"Software_Development/Development_Tools/#communication--im","text":"Slack Trillian / Pandion Skype, WeChat, Viber, Hangouts","title":"Communication / IM"},{"location":"Software_Development/Development_Tools/#wiki--knowledge-base","text":"Confluence Evernote","title":"Wiki / Knowledge Base"},{"location":"Software_Development/Development_Tools/#project--bug-tracking","text":"JIRA Bugzilla Mantis RedMine TFS","title":"Project / Bug Tracking"},{"location":"Software_Development/Development_Tools/#enterprise-architecture--uml","text":"Violet UML Editor Visio Rational Rose","title":"Enterprise Architecture / UML"},{"location":"Software_Development/Development_Tools/#terminals--ssh","text":"Putty MobaXterm mRemoteNG Remote Desktop Connection Manager","title":"Terminals / SSH"},{"location":"Software_Development/Development_Tools/#editors-ides","text":"Comparison of integrated development environments Notepad++ Plugins Gedit Sublime Text Eclipse List of Eclipse-based software Visual Studio Visual Studio Code for Python Python Tools for Visual Studio PyDev PyCharm Anaconda","title":"Editors/ IDEs"},{"location":"Software_Development/Development_Tools/#source-control","text":"SourceTree (Atlassian) GitHub TortoiseGit","title":"Source Control"},{"location":"Software_Development/Development_Tools/#code-quality","text":"SonarQube Phabricator Code Coverage","title":"Code Quality"},{"location":"Software_Development/Development_Tools/#virtual-machines-and-containers","text":"Oracle Virtualbox Docker Kubernetes","title":"Virtual Machines and Containers"},{"location":"Software_Development/Development_Tools/#sql-tools","text":"MySQL Workbench HeidiSQL Aginity Workbench for Redshift (AWS)","title":"SQL Tools"},{"location":"Software_Development/Development_Tools/#mongodb-tools","text":"RoboMongo MongoChef MongoDB Compass","title":"MongoDB tools"},{"location":"Software_Development/Development_Tools/#data-quality","text":"DQ Analyzer (Attacama)","title":"Data Quality"},{"location":"Software_Development/Development_Tools/#data-science","text":"Jupyter / IPython Rodeo Gephi","title":"Data Science"},{"location":"Software_Development/Development_Tools/#aws","text":"S3 Browser FastGlacier","title":"AWS"},{"location":"Software_Development/Development_Tools/#file-handling","text":"7zip FileZilla FolderSize","title":"File Handling"},{"location":"Software_Development/Development_Tools/#other","text":"Cygwin Log Tail Diff - WinMerge","title":"Other"},{"location":"Software_Development/Eclipse/","text":"Useful Links \u00b6 Eclipse AWS Toolkit for Eclipse Spring Tool Suite To install the AWS Toolkit \u00b6 Open Help > Install New Software . Enter https://aws.amazon.com/eclipse in the text box labeled \u201cWork with\u201d at the top of the dialog. Select \u201cAWS Toolkit for Eclipse\u201d from the list below.","title":"Eclipse"},{"location":"Software_Development/Eclipse/#useful-links","text":"Eclipse AWS Toolkit for Eclipse Spring Tool Suite","title":"Useful Links"},{"location":"Software_Development/Eclipse/#to-install-the-aws-toolkit","text":"Open Help > Install New Software . Enter https://aws.amazon.com/eclipse in the text box labeled \u201cWork with\u201d at the top of the dialog. Select \u201cAWS Toolkit for Eclipse\u201d from the list below.","title":"To install the AWS Toolkit"},{"location":"Software_Development/IntelliJ/","text":"IntelliJ \u00b6 Shortcuts \u00b6 Search Anywhere Double Shift Got to file Ctrl + Shift + N Recent files Ctrl + E Code Completion Ctrl + Space Parameters Ctrl + P Highlight usages in file Ctrl + Shift + F7 Declaration of the current method Alt + Q Code Templates Ctrl + J","title":"IntelliJ Cheatsheet"},{"location":"Software_Development/IntelliJ/#intellij","text":"","title":"IntelliJ"},{"location":"Software_Development/IntelliJ/#shortcuts","text":"Search Anywhere Double Shift Got to file Ctrl + Shift + N Recent files Ctrl + E Code Completion Ctrl + Space Parameters Ctrl + P Highlight usages in file Ctrl + Shift + F7 Declaration of the current method Alt + Q Code Templates Ctrl + J","title":"Shortcuts"},{"location":"Web/Bootstrap/","text":"Bootstrap \u00b6 Useful Links \u00b6 Bootstrap Install \u00b6 $ npm install bootstrap CDN \u00b6 < link rel = \"stylesheet\" href = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css\" integrity = \"sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7\" crossorigin = \"anonymous\" > < link rel = \"stylesheet\" href = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css\" integrity = \"sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r\" crossorigin = \"anonymous\" > < script src = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js\" integrity = \"sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS\" crossorigin = \"anonymous\" >","title":"Bootstrap"},{"location":"Web/Bootstrap/#bootstrap","text":"","title":"Bootstrap"},{"location":"Web/Bootstrap/#useful-links","text":"Bootstrap","title":"Useful Links"},{"location":"Web/Bootstrap/#install","text":"$ npm install bootstrap","title":"Install"},{"location":"Web/Bootstrap/#cdn","text":" < link rel = \"stylesheet\" href = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css\" integrity = \"sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7\" crossorigin = \"anonymous\" > < link rel = \"stylesheet\" href = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css\" integrity = \"sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r\" crossorigin = \"anonymous\" > < script src = \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js\" integrity = \"sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS\" crossorigin = \"anonymous\" >","title":"CDN"},{"location":"Web/CORS/","text":"CORS \u00b6 CORS on Wikipedia Same-origin_policy CORS Certain \"cross-domain\" requests, notably AJAX requests, are forbidden by default by the same-origin security policy of web browsers. The same-origin policy is an important security concept implemented by web browsers to prevent Javascript code from making requests against a different origin (e.g., different domain, more precisely combination of URI scheme, hostname, and port number ) than the one from which it was served. Although the same-origin policy is effective in preventing resources from different origins, it also prevents legitimate interactions between a server and clients of a known and trusted origin. Cross-Origin Resource Sharing (CORS) is a technique for relaxing the same-origin policy, allowing Javascript on a web page to consume a REST API served from a different origin. Cross-origin requests come in two flavors: 1. simple requests 2. \"not-so-simple requests\" (a term just made up) Simple Requests \u00b6 Simple requests are requests that meet the following criteria: HTTP Method matches (case-sensitive) one of: - HEAD - GET - POST HTTP Headers matches (case-insensitive): - Accept - Accept-Language - Content-Language - Last-Event-ID - Content-Type, but only if the value is one of application/x-www-form-urlencoded , multipart/form-data , text/plain Handling a not-so-simple request \u00b6 A not-so-simple request looks like a single request to the client, but it actually consists of two requests under the hood. The browser first issues a preflight request, which is like asking the server for permission to make the actual request. Once permissions have been granted, the browser makes the actual request. The browser handles the details of these two requests transparently. The preflight response can also be cached so that it is not issued on every request. Some Javascript libraries, such as AngularJS and Sencha Touch, send preflight requests for any kind of request. This approach is arguably safer, because it doesn't assume that a service adheres to HTTP method semantics (i.e., a GET endpoint could have been written to have side effects.) API Gateway and CORS \u00b6 How to CORS (AWS)","title":"CORS"},{"location":"Web/CORS/#cors","text":"CORS on Wikipedia Same-origin_policy CORS Certain \"cross-domain\" requests, notably AJAX requests, are forbidden by default by the same-origin security policy of web browsers. The same-origin policy is an important security concept implemented by web browsers to prevent Javascript code from making requests against a different origin (e.g., different domain, more precisely combination of URI scheme, hostname, and port number ) than the one from which it was served. Although the same-origin policy is effective in preventing resources from different origins, it also prevents legitimate interactions between a server and clients of a known and trusted origin. Cross-Origin Resource Sharing (CORS) is a technique for relaxing the same-origin policy, allowing Javascript on a web page to consume a REST API served from a different origin. Cross-origin requests come in two flavors: 1. simple requests 2. \"not-so-simple requests\" (a term just made up)","title":"CORS"},{"location":"Web/CORS/#simple-requests","text":"Simple requests are requests that meet the following criteria: HTTP Method matches (case-sensitive) one of: - HEAD - GET - POST HTTP Headers matches (case-insensitive): - Accept - Accept-Language - Content-Language - Last-Event-ID - Content-Type, but only if the value is one of application/x-www-form-urlencoded , multipart/form-data , text/plain","title":"Simple Requests"},{"location":"Web/CORS/#handling-a-not-so-simple-request","text":"A not-so-simple request looks like a single request to the client, but it actually consists of two requests under the hood. The browser first issues a preflight request, which is like asking the server for permission to make the actual request. Once permissions have been granted, the browser makes the actual request. The browser handles the details of these two requests transparently. The preflight response can also be cached so that it is not issued on every request. Some Javascript libraries, such as AngularJS and Sencha Touch, send preflight requests for any kind of request. This approach is arguably safer, because it doesn't assume that a service adheres to HTTP method semantics (i.e., a GET endpoint could have been written to have side effects.)","title":"Handling a not-so-simple request"},{"location":"Web/CORS/#api-gateway-and-cors","text":"How to CORS (AWS)","title":"API Gateway and CORS"},{"location":"Web/jQuery/","text":"jQuery \u00b6 Links \u00b6 jQuery API documentation Learn jQuery The jQuery library exposes its methods and properties via two properties of the window object called jQuery and $. $ is simply an alias for jQuery and it's often employed because it's shorter and faster to write. Embed JQuery \u00b6 Either directly < html > < head > < meta charset = \"utf-8\" > < title > Demo < body > < a href = \"http://jquery.com/\" > jQuery < script src = \"jquery.js\" > < script > // Your code goes here. or via a CDN < head > < script src = \"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\" > Launching Code on Document Ready \u00b6 $ ( document ). ready ( function () { // Your code here. }); // Shorthand for $( document ).ready() $ ( function () { console . log ( \"ready!\" ); }); Selecting elements \u00b6 $ ( \"#myId\" ); // Note IDs must be unique per page. $ ( \".myClass\" ); $ ( \"input[name='first_name']\" ); $ ( \"#contents ul.people li\" ); $ ( \"div.myClass, ul.people\" ); If you have a variable containing a DOM element, and want to select elements related to that DOM element, simply wrap it in a jQuery object. var myDomElement = document . getElementById ( \"foo\" ); // A plain DOM element. $ ( myDomElement ). find ( \"a\" ); // Finds all anchors inside the DOM element. Pull a native DOM element from a jQuery object \u00b6 A jQuery object is an array-like wrapper around one or more DOM elements. $ ( \"#foo\" )[ 0 ]; // Equivalent to document.getElementById( \"foo\" ) $ ( \"#foo\" ). get ( 0 ); // Testing whether a selection contains elements. if ( $ ( \"div.foo\" ). length ) { ... } Refining selections. \u00b6 $ ( \"div.foo\" ). has ( \"p\" ); // div.foo elements that contain

tags $ ( \"h1\" ). not ( \".bar\" ); // h1 elements that don't have a class of bar $ ( \"ul li\" ). filter ( \".current\" ); // unordered list items with class of current $ ( \"ul li\" ). first (); // just the first unordered list item $ ( \"ul li\" ). eq ( 5 ); // the sixth $ ( \"form :checked\" ); // :checked targets checked checkboxes DOM Traversal and Manipulation \u00b6 Get the Styles \u00b6 Triggers \u00b6 ","title":"WPF"},{"location":"dotNET/WPF/#useful-links","text":"WPF tutorial WPF Documentation WPF Samples WPF Tools","title":"Useful Links"},{"location":"dotNET/WPF/#application","text":" ","title":"Application"},{"location":"dotNET/WPF/#commands","text":"WPF Commands WPF provides a set of predefined commands. The command library consists of the following classes: ApplicationCommands, NavigationCommands, MediaCommands, EditingCommands, and the ComponentCommands.

","title":"Commands"},{"location":"dotNET/WPF/#page","text":" ","title":"Page"},{"location":"dotNET/WPF/#styles","text":" ","title":"Styles"},{"location":"dotNET/WPF/#triggers","text":"","title":"Triggers"}]} \ No newline at end of file diff --git a/docs_src/Software_Development/Development_Tools.md b/docs/Software_Development/Development_Tools.md similarity index 69% rename from docs_src/Software_Development/Development_Tools.md rename to docs/Software_Development/Development_Tools.md index c5f0aa8..2d9f107 100644 --- a/docs_src/Software_Development/Development_Tools.md +++ b/docs/Software_Development/Development_Tools.md @@ -11,13 +11,11 @@ comments: true - Trillian / Pandion - Skype, WeChat, Viber, Hangouts - ## Wiki / Knowledge Base - Confluence - Evernote - ## Project / Bug Tracking - JIRA @@ -26,13 +24,11 @@ comments: true - RedMine - TFS - ## [Enterprise Architecture / UML]( https://en.wikipedia.org/wiki/List_of_Unified_Modeling_Language_tools ) - Violet UML Editor - Visio -- Rational Rose - +- Rational Rose ## Terminals / SSH @@ -41,24 +37,20 @@ comments: true - mRemoteNG - Remote Desktop Connection Manager - ## Editors/ IDEs -- [Comparison of integrated development environments]( http://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments ) - +- [Comparison of integrated development environments]( https://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments ) - [Notepad++]( https://notepad-plus-plus.org/ ) - - [Plugins]( http://www.guidingtech.com/31357/notepad-plus-plugins/ ) + - [Plugins]( https://www.guidingtech.com/31357/notepad-plus-plugins/ ) - Gedit - Sublime Text - -- [Eclipse]( http://www.eclipse.org/ ) - - [List of Eclipse-based software]( http://en.wikipedia.org/wiki/List_of_Eclipse-based_software ) +- [Eclipse]( https://www.eclipse.org/ ) + - [List of Eclipse-based software]( https://en.wikipedia.org/wiki/List_of_Eclipse-based_software ) - Visual Studio - Visual Studio Code - _for Python_ - Python Tools for Visual Studio @@ -66,21 +58,18 @@ _for Python_ - PyCharm - Anaconda - ## Source Control - SourceTree (Atlassian) - GitHub - TortoiseGit - ## Code Quality -- [SonarQube]( http://www.sonarqube.org/ ) -- [Phabricator]( https://www.phacility.com/ ) +- [SonarQube]( https://www.sonarqube.org/ ) +- [Phabricator]( https://www.phacility.com/ ) - [Code Coverage]( https://codecov.io/ ) - ## Virtual Machines and Containers - [Oracle Virtualbox]( https://www.virtualbox.org/ ) @@ -88,48 +77,41 @@ _for Python_ - Docker - Kubernetes - ## SQL Tools - MySQL Workbench - HeidiSQL - Aginity Workbench for Redshift (AWS) - ## MongoDB tools - RoboMongo - MongoChef - MongoDB Compass - ## Data Quality - DQ Analyzer (Attacama) - ## Data Science - Jupyter / IPython - Rodeo - Gephi - ## AWS - S3 Browser - FastGlacier - ## File Handling -- [7zip](http://www.7-zip.org/) +- [7zip](https://www.7-zip.org/) - FileZilla - FolderSize - ## Other - [Cygwin](https://www.cygwin.com/) -- [Log Tail]( http://www.log-expert.de/) -- [Diff - WinMerge](http://winmerge.org/) \ No newline at end of file +- [Log Tail]( https://www.log-expert.de/) +- [Diff - WinMerge](https://winmerge.org/) diff --git a/docs/Software_Development/Development_Tools/index.html b/docs/Software_Development/Development_Tools/index.html deleted file mode 100644 index 7b660d8..0000000 --- a/docs/Software_Development/Development_Tools/index.html +++ /dev/null @@ -1,2290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Development Tools - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

Development Tools

- -

Communication / IM

-
    -
  • Slack
  • -
  • Trillian / Pandion
  • -
  • Skype, WeChat, Viber, Hangouts
  • -
-

Wiki / Knowledge Base

-
    -
  • Confluence
  • -
  • Evernote
  • -
-

Project / Bug Tracking

-
    -
  • JIRA
  • -
  • Bugzilla
  • -
  • Mantis
  • -
  • RedMine
  • -
  • TFS
  • -
-

Enterprise Architecture / UML

-
    -
  • Violet UML Editor
  • -
  • Visio
  • -
  • Rational Rose
  • -
-

Terminals / SSH

-
    -
  • Putty
  • -
  • MobaXterm
  • -
  • mRemoteNG
  • -
  • Remote Desktop Connection Manager
  • -
-

Editors/ IDEs

- -

for Python

-
    -
  • Python Tools for Visual Studio
  • -
  • PyDev
  • -
  • PyCharm
  • -
  • Anaconda
  • -
-

Source Control

-
    -
  • SourceTree (Atlassian)
  • -
  • GitHub
  • -
  • TortoiseGit
  • -
-

Code Quality

- -

Virtual Machines and Containers

- -

SQL Tools

-
    -
  • MySQL Workbench
  • -
  • HeidiSQL
  • -
  • Aginity Workbench for Redshift (AWS)
  • -
-

MongoDB tools

-
    -
  • RoboMongo
  • -
  • MongoChef
  • -
  • MongoDB Compass
  • -
-

Data Quality

-
    -
  • DQ Analyzer (Attacama)
  • -
-

Data Science

-
    -
  • Jupyter / IPython
  • -
  • Rodeo
  • -
  • Gephi
  • -
-

AWS

-
    -
  • S3 Browser
  • -
  • FastGlacier
  • -
-

File Handling

-
    -
  • 7zip
  • -
  • FileZilla
  • -
  • FolderSize
  • -
-

Other

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Software_Development/Eclipse.md b/docs/Software_Development/Eclipse.md similarity index 88% rename from docs_src/Software_Development/Eclipse.md rename to docs/Software_Development/Eclipse.md index 49742e8..ac3382e 100644 --- a/docs_src/Software_Development/Eclipse.md +++ b/docs/Software_Development/Eclipse.md @@ -1,15 +1,11 @@ - -## Useful Links +# Useful Links * [Eclipse]( https://eclipse.org/downloads/ ) * [AWS Toolkit for Eclipse]( https://aws.amazon.com/eclipse/ ) * [Spring Tool Suite]( https://spring.io/tools ) - -### To install the AWS Toolkit +## To install the AWS Toolkit 1. Open ``Help`` > ``Install New Software``. 2. Enter [https://aws.amazon.com/eclipse](https://aws.amazon.com/eclipse) in the text box labeled “Work with” at the top of the dialog. 3. Select “AWS Toolkit for Eclipse” from the list below. - - diff --git a/docs/Software_Development/Eclipse/index.html b/docs/Software_Development/Eclipse/index.html deleted file mode 100644 index 9cc2d5c..0000000 --- a/docs/Software_Development/Eclipse/index.html +++ /dev/null @@ -1,1992 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Eclipse - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Software_Development/IntelliJ.md b/docs/Software_Development/IntelliJ.md similarity index 100% rename from docs_src/Software_Development/IntelliJ.md rename to docs/Software_Development/IntelliJ.md diff --git a/docs/Software_Development/IntelliJ/index.html b/docs/Software_Development/IntelliJ/index.html deleted file mode 100644 index 9924bae..0000000 --- a/docs/Software_Development/IntelliJ/index.html +++ /dev/null @@ -1,1971 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - IntelliJ Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

IntelliJ

-

Shortcuts

-
Search Anywhere     Double Shift
-Got to file         Ctrl + Shift + N
-Recent files        Ctrl + E
-Code Completion     Ctrl + Space 
-Parameters          Ctrl + P
-Highlight usages in file            Ctrl + Shift + F7
-Declaration of the current method   Alt + Q
-Code Templates      Ctrl + J
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Web/Bootstrap.md b/docs/Web/Bootstrap.md similarity index 93% rename from docs_src/Web/Bootstrap.md rename to docs/Web/Bootstrap.md index e44de53..188f042 100644 --- a/docs_src/Web/Bootstrap.md +++ b/docs/Web/Bootstrap.md @@ -8,13 +8,12 @@ tags: Bootstrap web CSS ### Useful Links -[Bootstrap]( http://getbootstrap.com/) - +[Bootstrap]( https://getbootstrap.com/) ### Install ```sh -$ npm install bootstrap +npm install bootstrap ``` ### CDN diff --git a/docs/Web/Bootstrap/index.html b/docs/Web/Bootstrap/index.html deleted file mode 100644 index bdd7695..0000000 --- a/docs/Web/Bootstrap/index.html +++ /dev/null @@ -1,2024 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Bootstrap - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

Bootstrap

- -

Bootstrap

- -

Bootstrap

-

Install

-
$ npm install bootstrap
-
- -

CDN

-
<!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
-
-<!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
-
-<!-- Latest compiled and minified JavaScript --><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
-
- - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Web/CORS.md b/docs/Web/CORS.md similarity index 99% rename from docs_src/Web/CORS.md rename to docs/Web/CORS.md index 209a7ac..67b9bba 100644 --- a/docs_src/Web/CORS.md +++ b/docs/Web/CORS.md @@ -11,6 +11,7 @@ The same-origin policy is an important security concept implemented by web brows Cross-Origin Resource Sharing (CORS) is a technique for relaxing the same-origin policy, allowing Javascript on a web page to consume a REST API served from a different origin. Cross-origin requests come in two flavors: + 1. simple requests 2. "not-so-simple requests" (a term just made up) @@ -19,11 +20,13 @@ Cross-origin requests come in two flavors: Simple requests are requests that meet the following criteria: HTTP Method matches (case-sensitive) one of: + - HEAD - GET - POST - + HTTP Headers matches (case-insensitive): + - Accept - Accept-Language - Content-Language @@ -36,13 +39,6 @@ A not-so-simple request looks like a single request to the client, but it actual Some Javascript libraries, such as AngularJS and Sencha Touch, send preflight requests for any kind of request. This approach is arguably safer, because it doesn't assume that a service adheres to HTTP method semantics (i.e., a GET endpoint could have been written to have side effects.) - ## API Gateway and CORS [How to CORS (AWS)]( https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html ) - - - - - - diff --git a/docs/Web/CORS/index.html b/docs/Web/CORS/index.html deleted file mode 100644 index 4493ceb..0000000 --- a/docs/Web/CORS/index.html +++ /dev/null @@ -1,2015 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - CORS - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - -
-
-
- - -
-
- - - - - - - -

CORS

- -

Certain "cross-domain" requests, notably AJAX requests, are forbidden by default by the same-origin security policy of web browsers.

-

The same-origin policy is an important security concept implemented by web browsers to prevent Javascript code from making requests against a different origin (e.g., different domain, more precisely combination of URI scheme, hostname, and port number ) than the one from which it was served. Although the same-origin policy is effective in preventing resources from different origins, it also prevents legitimate interactions between a server and clients of a known and trusted origin.

-

Cross-Origin Resource Sharing (CORS) is a technique for relaxing the same-origin policy, allowing Javascript on a web page to consume a REST API served from a different origin.

-

Cross-origin requests come in two flavors: -1. simple requests -2. "not-so-simple requests" (a term just made up)

-

Simple Requests

-

Simple requests are requests that meet the following criteria:

-

HTTP Method matches (case-sensitive) one of: -- HEAD -- GET -- POST

-

HTTP Headers matches (case-insensitive): -- Accept -- Accept-Language -- Content-Language -- Last-Event-ID -- Content-Type, but only if the value is one of application/x-www-form-urlencoded, multipart/form-data, text/plain

-

Handling a not-so-simple request

-

A not-so-simple request looks like a single request to the client, but it actually consists of two requests under the hood. The browser first issues a preflight request, which is like asking the server for permission to make the actual request. Once permissions have been granted, the browser makes the actual request. The browser handles the details of these two requests transparently. The preflight response can also be cached so that it is not issued on every request.

-

Some Javascript libraries, such as AngularJS and Sencha Touch, send preflight requests for any kind of request. This approach is arguably safer, because it doesn't assume that a service adheres to HTTP method semantics (i.e., a GET endpoint could have been written to have side effects.)

-

API Gateway and CORS

-

How to CORS (AWS)

- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Web/jQuery.md b/docs/Web/jQuery.md similarity index 94% rename from docs_src/Web/jQuery.md rename to docs/Web/jQuery.md index 3fe72b3..cd6676f 100644 --- a/docs_src/Web/jQuery.md +++ b/docs/Web/jQuery.md @@ -2,8 +2,8 @@ ## Links -- [jQuery API documentation]( http://api.jquery.com/ ) -- [Learn jQuery]( http://learn.jquery.com/ ) +- [jQuery API documentation]( https://api.jquery.com/ ) +- [Learn jQuery]( https://learn.jquery.com/ ) The jQuery library exposes its methods and properties via two properties of the window object called jQuery and $. $ is simply an alias for jQuery and it's often employed because it's shorter and faster to write. @@ -19,7 +19,7 @@ Either directly Demo -jQuery +jQuery - - - - - - - - - - - - - - - - - - - - -
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - -
-
- - - - - - - -

jQuery

- - -

The jQuery library exposes its methods and properties via two properties of the window object called jQuery and $. $ is simply an alias for jQuery and it's often employed because it's shorter and faster to write.

-

Embed JQuery

-

Either directly

-
<!doctype html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Demo</title>
-</head>
-<body>
-<a href="http://jquery.com/">jQuery</a>
-<script src="jquery.js"></script>
-<script>
-// Your code goes here.
-</script>
-</body>
-
- -

or via a CDN

-
<head>
-<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
-</head>
-
- -

Launching Code on Document Ready

-
$( document ).ready(function() {
-// Your code here.
-});
-
-// Shorthand for $( document ).ready()
-$(function() {
-console.log( "ready!" );
-});
-
- -

Selecting elements

-
$( "#myId" ); // Note IDs must be unique per page.
-$( ".myClass" );
-$( "input[name='first_name']" );
-$( "#contents ul.people li" );
-$( "div.myClass, ul.people" );
-
- -

If you have a variable containing a DOM element, and want to select elements related to that DOM element, simply wrap it in a jQuery object.

-
var myDomElement = document.getElementById( "foo" ); // A plain DOM element.
-$( myDomElement ).find( "a" ); // Finds all anchors inside the DOM element.
-
- -

Pull a native DOM element from a jQuery object

-

A jQuery object is an array-like wrapper around one or more DOM elements.

-
$( "#foo" )[ 0 ]; // Equivalent to document.getElementById( "foo" )
-$( "#foo" ).get( 0 );
-
- -

// Testing whether a selection contains elements.

-
if ( $( "div.foo" ).length ) {
-...
-}
-
- -

Refining selections.

-
$( "div.foo" ).has( "p" ); // div.foo elements that contain <p> tags
-$( "h1" ).not( ".bar" ); // h1 elements that don't have a class of bar
-$( "ul li" ).filter( ".current" ); // unordered list items with class of current
-$( "ul li" ).first(); // just the first unordered list item
-$( "ul li" ).eq( 5 ); // the sixth
-
-$( "form :checked" ); //  :checked targets checked checkboxes
-
- -

DOM Traversal and Manipulation

-

Get the <button> element with the class 'continue' and change its HTML to 'Next Step...'

-
$( "button.continue" ).html( "Next Step..." )
-$( "h1" ).html(); // returns the html
-
- -

Chaining

-
$( "#content" ).find( "h3" ).eq( 2 ).html( "new text for the third h3!" ); 
-$( "#content" )
-.find( "h3" )
-.eq( 2 )
-.html( "new text for the third h3!" )
-.end() // Restores the selection to all h3s in #content
-.eq( 0 )
-.html( "new text for the first h3!" );
-
- -

Manipulation

-
    -
  • .html() – Get or set the HTML contents.
  • -
  • .text() – Get or set the text contents; HTML will be stripped.
  • -
  • .attr() – Get or set the value of the provided attribute.
  • -
  • .width() – Get or set the width in pixels of the first element in the selection as an integer.
  • -
  • .height() – Get or set the height in pixels of the first element in the selection as an integer.
  • -
  • .position() – Get an object with position information for the first element in the selection, relative to its first positioned ancestor. This is a getter only.
  • -
  • .val() – Get or set the value of form elements.
  • -
-

Many jQuery methods implicitly iterate over the entire collection, applying their behavior to each matched element. In most cases, the "getter" signature returns the result from the first element in a jQuery collection while the setter acts over the entire collection of matched elements.

-
$( "li" ).addClass( "newClass" ); // Each <li> in the document will have the class "newClass" added.
-
- -

Add / remove class

-
$( "a" ).addClass( "test" );
-$( "a" ).removeClass( "test" );
-
-$( "div" ).click(function() {
-if ( $( this ).hasClass( "protected" ) ) {
-$( this )
-.animate({ left: -10 })
-.animate({ left: 10 })
-.animate({ left: -10 })
-.animate({ left: 10 })
-.animate({ left: 0 });
-}
-});
-
-if ( $( "#myDiv" ).is( ".pretty.awesome" ) ) {
-$( "#myDiv" ).show();
-}
-var isVisible = $( "#myDiv" ).is( ":visible" );
-if ( $( "#myDiv" ).is( ":hidden" ) ) {
-$( "#myDiv" ).show();
-}
-
- -

Set / get element attributes

-
$( "a" ).attr( "href", "allMyHrefsAreTheSameNow.html" );
-$( "a" ).attr({
-title: "all titles are the same too!",
-href: "somethingNew.html"
-});
-
- -

CSS

-

Getting CSS properties.

-
$( "h1" ).css( "fontSize" ); // Returns a string such as "19px".$( "h1" ).css( "font-size" ); // Also works.
-
- -

Setting CSS properties.

-
$( "h1" ).css( "fontSize", "100px" ); // Setting an individual property.// Setting multiple properties.$( "h1" ).css({fontSize: "100px",color: "red"});
-
- -

Data

-

Storing and retrieving data related to an element.

-
$( "#myDiv" ).data( "keyName", { foo: "bar" } );
-$( "#myDiv" ).data( "keyName" ); // Returns { foo: "bar" }
-
- -

Storing a relationship between elements using .data()

-
$( "#myList li" ).each(function() {
-var li = $( this );
-var div = li.find( "div.content" );
-li.data( "contentDiv", div );
-});
-
- -

Later, we don't have to find the div again; we can just read it from the list item's data

-
var firstLi = $( "#myList li:first" );
-firstLi.data( "contentDiv" ).html( "new content" );
-
- -

Utility functions

-

.trim, .each, .map, inArray, isArray, isFunction, isNumeric, .type

-

Returns "lots of extra whitespace"

-
$.trim( " lots of extra whitespace " );
-
- -

Iterate over an JS array or object

-
$.each([ "foo", "bar", "baz" ], function( idx, val ) {
-console.log( "element " + idx + " is " + val );
-});
-$.each({ foo: "bar", baz: "bim" }, function( k, v ) {
-console.log( k + " : " + v );
-});
-
- -

HOWEVER, use this form for jQuery objects

-
$( "li" ).each( function( index, element ){
-console.log( $( this ).text() );
-});
-
-var myArray = [ 1, 2, 3, 5 ];
-if ( $.inArray( 4, myArray ) !== -1 ) {
-console.log( "found it!" );
-}
-
- -
$.isArray([]); // true
-$.isFunction(function() {}); // true
-$.isNumeric(3.14); // true
-
-$.type( true ); // "boolean"
-$.type( 3 ); // "number"
-$.type( "test" ); // "string"
-$.type( function() {} ); // "function"
-$.type( new Boolean() ); // "boolean"
-$.type( new Number(3) ); // "number"
-$.type( new String('test') ); // "string"
-$.type( new Function() ); // "function"
-$.type( [] ); // "array"
-$.type( null ); // "null"
-$.type( /test/ ); // "regexp"
-$.type( new Date() ); // "date"
-
- -

$.map and .map

-
<li id="a"></li>
-<li id="b"></li>
-<li id="c"></li>
-<script>
-var arr = [{
-id: "a",
-tagName: "li"
-}, {
-id: "b",
-tagName: "li"
-}, {
-id: "c",
-tagName: "li"
-}];
-
-// Returns [ "a", "b", "c" ]
-$( "li" ).map( function( index, element ) {
-return element.id;
-}).get();
-
-// Also returns [ "a", "b", "c" ]
-// Note that the value comes first with $.map
-$.map( arr, function( value, index ) {
-return value.id;
-});
-
- -

Event Handling

-
var hiddenBox = $( "#banner-message" );
-$( "#button-container button" ).on( "click", function( event ) {
-hiddenBox.show();
-});
-
- -

The on method is useful for binding the same handler function to multiple events, when you want to provide data to the event handler, when you are working with custom events, or when you want to pass an object of multiple events and handlers.

-

Event setup using a convenience method like .click(), .focus(), .blur(), .change()

-
$( "p" ).click(function() {
-console.log( "You clicked a paragraph!" );
-});
-
- -

The hover helper function

-
$( "#menu li" ).hover(function() {
-$( this ).toggleClass( "hover" );
-});
-
- -

The event object is most commonly used to prevent the default action of the event via the .preventDefault() method. However, the event object contains a number of other useful properties and methods, including:

-
pageX, pageY, type, which, data
-
- -

Use this code to inspect it in your browser console

-
$( "div" ).on( "click", function( event ) {
-console.log( "event object:" );
-console.dir( event );
-});
-
- - -
$( "a" ).click(function( eventObject ) {
-var elem = $( this );
-if ( elem.attr( "href" ).match( /evil/ ) ) {
-eventObject.preventDefault();
-elem.addClass( "evil" );
-}
-});
-
- -

Event setup using the .on() method with data

-
$( "input" ).on(
-"change",
-{ foo: "bar" }, // Associate data with event binding
-function( eventObject ) {
-console.log("An input value has changed! ", eventObject.data.foo);
-}
-);
-
- -

// Binding multiple events with different handlers

-
$( "p" ).on({
-"click": function() { console.log( "clicked!" ); },
-"mouseover": function() { console.log( "hovered!" ); }
-});
-
- -

// Tearing down all click handlers on a selection

-
$( "p" ).off( "click" );
-
- -

// As of jQuery 1.7, attach an event handler to the body element that -// is listening for clicks, and will respond whenever any button is -// clicked on the page.

-
$( "body" ).on({
-click: function( event ) {
-alert( "Hello." );
-}
-}, "button" );
-
- -

// An alternative to the previous example, using slightly different syntax.

-
$( "body" ).on( "click", "button", function( event ) {
-alert( "Hello." );
-});
-
- -

// Attach a delegated event handler with a more refined selector

-
$( "#list" ).on( "click", "a[href^='http']", function( event ) {
-$( this ).attr( "target", "_blank" );
-});
-
- -

Effects

-

Instantaneously hide all paragraphs

-
$( "p" ).hide();
-
-// slowly
-$( "p" ).hide( "slow" ); 
-
- -

Instantaneously show all divs that have the hidden style class

-
$( "div.hidden" ).show();
-
- -

Instantaneously toggle the display of all paragraphs

-
$( "p" ).toggle();
-
- -

Fade in all hidden paragraphs; then add a style class to them (correct with animation callback)

-
$( "p.hidden" ).fadeIn( 750, function() {
-// this = DOM element which has just finished being animated
-$( this ).addClass( "lookAtMe" );
-});
-
- -

Ajax

-
$.ajax({
-url: "/api/getWeather",
-data: {
-zipcode: 97201
-},
-success: function( result ) {
-$( "#weather-temp" ).html( "<strong>" + result + "</strong> degrees" );
-}
-});
-
- -

Using the core $.ajax() method

-
$.ajax({
-// The URL for the request
-url: "post.php",
-// The data to send (will be converted to a query string)
-data: {
-id: 123
-},
-// Whether this is a POST or GET request
-type: "GET",
-// The type of data we expect back
-dataType : "json",
-})
-// Code to run if the request succeeds (is done);
-// The response is passed to the function
-.done(function( json ) {
-$( "<h1>" ).text( json.title ).appendTo( "body" );
-$( "<div class=\"content\">").html( json.html ).appendTo( "body" );
-})
-// Code to run if the request fails; the raw request and
-// status codes are passed to the function
-.fail(function( xhr, status, errorThrown ) {
-alert( "Sorry, there was a problem!" );
-console.log( "Error: " + errorThrown );
-console.log( "Status: " + status );
-console.dir( xhr );
-})
-
- -

Code to run regardless of success or failure;

-
.always(function( xhr, status ) {
-alert( "The request is complete!" );
-});
-
- -

Simple convenience methods such as $.get(), $.getScript(), $.getJSON(), $.post(), and $().load().

-
$.get( "myhtmlpage.html", myCallBack );  // myCallback needs to be a parameterless function
-# with parameters
-$.get( "myhtmlpage.html", function() {
-myCallBack( param1, param2 );
-});
-
- -

Load

-
$(selector).load(URL,data,callback);
-
- -

Using .load() to populate an element

-
$( "#newContent" ).load( "/foo.html" );
-
- -

Using .load() to populate an element based on a selector

-
$( "#newContent" ).load( "/foo.html #myDiv h1:first", function( html ) {
-alert( "Content updated!" );
-});
-
- -

Forms

-

Turning form data into a query string

-
$( "#myForm" ).serialize();
-
- -

// Creates a query string like this: -// field_1=something&field2=somethingElse

-

Create an array of objects containing form data

-
$( "#myForm" ).serializeArray();
-
- -

Use validation to check for the presence of an input

-
$( "#form" ).submit(function( event ) {
-// If .required's value's length is zero
-if ( $( ".required" ).val().length === 0 ) {
-// Usually show some kind of error message here
-// Prevent the form from submitting
-event.preventDefault();
-} else {
-// Run $.ajax() here
-}
-});
-
- -

Validate a phone number field

-
$( "#form" ).submit(function( event ) {
-var inputtedPhoneNumber = $( "#phone" ).val();
-// Match only numbers
-var phoneNumberRegex = /^\d*$/;
-// If the phone number doesn't match the regex
-if ( !phoneNumberRegex.test( inputtedPhoneNumber ) ) {
-// Usually show some kind of error message here
-// Prevent the form from submitting
-event.preventDefault();
-} else {
-// Run $.ajax() here
-}
-});
-
- -

Feature testing

-

Helper libraries (like Modernizr) that provide a simple, high-level API for determining if a browser has a specific feature available or not.

-
if ( Modernizr.canvas ) {
-showGraphWithCanvas();
-} else {
-showTable();
-}
-
- - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/Windows/Command_Prompt_Here.md b/docs/Windows/Command_Prompt_Here.md similarity index 94% rename from docs_src/Windows/Command_Prompt_Here.md rename to docs/Windows/Command_Prompt_Here.md index b58a3b5..0dfcf31 100644 --- a/docs_src/Windows/Command_Prompt_Here.md +++ b/docs/Windows/Command_Prompt_Here.md @@ -8,12 +8,9 @@ Just type "cmd" to the location bar. It will start a new command prompt in curre OR -Hold the "Shift" key while right-clicking a blank space in the desired folder to bring up a more verbose context menu. One of the options is "Open PowerShell Here". - +Hold the "Shift" key while right-clicking a blank space in the desired folder to bring up a more verbose context menu. One of the options is "Open PowerShell Here". To re-enable the "Open Command Prompt Here" (disabled by the Windows 10 Creators Update): - [Link]( https://superuser.com/questions/1201988/how-do-i-change-open-with-powershell-to-open-with-command-prompt-when-shift ) - [Link 2]( https://blogs.msdn.microsoft.com/andrew_richards/2017/03/01/enhancing-the-open-command-prompt-here-shift-right-click-context-menu-experience/ ) - - diff --git a/docs/Windows/Command_Prompt_Here/index.html b/docs/Windows/Command_Prompt_Here/index.html deleted file mode 100644 index 7649da9..0000000 --- a/docs/Windows/Command_Prompt_Here/index.html +++ /dev/null @@ -1,1903 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Command Line - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
- - - -
- -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
- - - - - - - -

Command Line

- -

Just type "cmd" to the location bar. It will start a new command prompt in current path.

-

OR

-

Hold the "Shift" key while right-clicking a blank space in the desired folder to bring up a more verbose context menu. One of the options is "Open PowerShell Here".

-

To re-enable the "Open Command Prompt Here" (disabled by the Windows 10 Creators Update):

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - \ No newline at end of file diff --git a/docs/assets/images/favicon.png b/docs/assets/images/favicon.png deleted file mode 100644 index 1cf13b9f9d978896599290a74f77d5dbe7d1655c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ diff --git a/docs/assets/javascripts/bundle.6ced434e.min.js b/docs/assets/javascripts/bundle.6ced434e.min.js deleted file mode 100644 index 3e5ac17..0000000 --- a/docs/assets/javascripts/bundle.6ced434e.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e,t){for(var c in t)e[c]=t[c]}(window,function(e){function t(t){for(var a,o,i=t[0],s=t[1],b=t[2],p=0,f=[];pObject(r.a)(new L.a(e=>{for(const t of e)U.next(t)}))).pipe(Object(f.a)(e=>Object(u.a)(Object(r.a)(e),o.a).pipe(Object(P.a)(()=>e.disconnect()))),Object(p.a)({bufferSize:1,refCount:!0}));function q(e){return H.pipe(Object(d.a)(t=>t.observe(e)),Object(f.a)(t=>U.pipe(Object(m.a)(({target:t})=>t===e),Object(P.a)(()=>t.unobserve(e)),Object(g.a)(({contentRect:e})=>({width:e.width,height:e.height})))),Object(C.a)(function(e){return{width:e.offsetWidth,height:e.offsetHeight}}(e)))}var I=c(73);var N=c(60);function D(e,t=location){return e.host===t.host&&/^(?:\/[\w-]+)*(?:\/?|\.html)$/i.test(e.pathname)}function Y(e,t=location){return e.pathname===t.pathname&&e.hash.length>0}function F(){return new N.a(new URL(location.href))}function J(){return location.hash.substring(1)}function K(e){const t=A("a");t.href=e,t.addEventListener("click",e=>e.stopPropagation()),t.click()}var W=c(5);function B(e){const t=matchMedia(e);return new W.a(e=>{t.addListener(t=>e.next(t.matches))}).pipe(Object(C.a)(t.matches),Object(p.a)({bufferSize:1,refCount:!0}))}const Q={drawer:S("[data-md-toggle=drawer]"),search:S("[data-md-toggle=search]")};function X(e,t){Q[e].checked!==t&&Q[e].click()}function V(e){const t=Q[e];return Object(b.a)(t,"change").pipe(Object(g.a)(()=>t.checked),Object(C.a)(t.checked))}function G(){return{x:Math.max(0,pageXOffset),y:Math.max(0,pageYOffset)}}function Z({x:e,y:t}){window.scrollTo(e||0,t||0)}function ee(){return{width:innerWidth,height:innerHeight}}function te(e,{header$:t,viewport$:c}){const a=c.pipe(Object($.a)("size")),n=Object(i.a)([a,t]).pipe(Object(g.a)(()=>({x:e.offsetLeft,y:e.offsetTop})));return Object(i.a)([t,c,n]).pipe(Object(g.a)(([{height:e},{offset:t,size:c},{x:a,y:n}])=>({offset:{x:t.x-a,y:t.y-n+e},size:c})))}var ce=c(62),ae=c(63);var ne=c(19),re=c(77),oe=c(44);let ie;function se(e){return ie.pipe(Object(f.a)(t=>void 0!==t[e]?Object(r.a)(t[e]):ne.a),Object(oe.a)())}var be=c(39),ue=c(78);function pe({document$:e,viewport$:t}){return Object(be.a)(Object(f.a)(c=>{const a=function(e,{document$:t}){return t.pipe(Object(g.a)(()=>{const t=getComputedStyle(e);return["sticky","-webkit-sticky"].includes(t.position)}),Object(oe.a)(),Object(f.a)(t=>t?q(e).pipe(Object(g.a)(({height:e})=>({sticky:!0,height:e}))):Object(r.a)({sticky:!1,height:0})),Object(p.a)({bufferSize:1,refCount:!0}))}(c,{document$:e}),n=se("main").pipe(Object(g.a)(e=>E("h1, h2, h3, h4, h5, h6",e)),Object(m.a)(e=>void 0!==e),Object(ue.a)(se("header-title")),Object(f.a)(([e,c])=>te(e,{header$:a,viewport$:t}).pipe(Object(g.a)(({offset:{y:t}})=>t>=e.offsetHeight?"page":"site"),Object(oe.a)(),function(e){return Object(be.a)(Object(h.a)(s.a),Object(d.a)(t=>{!function(e,t){e.setAttribute("data-md-state",t?"active":"")}(e,"page"===t)}),Object(P.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(e)}))}(c))),Object(C.a)("site"));return Object(i.a)([a,n]).pipe(Object(g.a)(([e,t])=>Object.assign({type:t},e)))}))}var fe=c(9);function le({header$:e,viewport$:t}){const c=new z.a;return se("header").pipe(Object(f.a)(e=>{return c.pipe(Object($.a)("active"),(t=e,Object(be.a)(Object(h.a)(s.a),Object(d.a)(({active:e})=>{!function(e,t){e.setAttribute("data-md-state",t?"shadow":"")}(t,e)}),Object(P.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(t)}))));var t})).subscribe(fe.a),Object(be.a)(Object(f.a)(c=>function(e,{header$:t,viewport$:c}){const a=t.pipe(Object(g.a)(({height:e})=>e),Object(oe.a)()),n=a.pipe(Object(f.a)(()=>q(e).pipe(Object(g.a)(({height:t})=>({top:e.offsetTop,bottom:e.offsetTop+t})),Object($.a)("bottom"))));return Object(i.a)([a,n,c]).pipe(Object(g.a)(([e,{top:t,bottom:c},{offset:{y:a},size:{height:n}}])=>({offset:t-e,height:n=Math.max(0,n-Math.max(0,t-a,e)-Math.max(0,n+a-c)),active:t-e<=a})),Object(oe.a)((e,t)=>e.offset===t.offset&&e.height===t.height&&e.active===t.active))}(c,{header$:e,viewport$:t})),Object(d.a)(e=>c.next(e)),Object(P.a)(()=>c.complete()))}function de(e){e.style.top=""}function Oe(e,{main$:t,viewport$:c}){const a=e.parentElement.offsetTop-e.parentElement.parentElement.offsetTop;return Object(i.a)([t,c]).pipe(Object(g.a)(([{offset:e,height:t},{offset:{y:c}}])=>({height:t=t+Math.min(a,Math.max(0,c-e))-a,lock:c>=e+a})),Object(oe.a)((e,t)=>e.height===t.height&&e.lock===t.lock))}function je(e,{header$:t}){return Object(be.a)(Object(h.a)(s.a),Object(j.a)(t),Object(d.a)(([{height:t,lock:c},{height:a}])=>{!function(e,t){const c=e.firstElementChild;c.style.height=t-2*c.offsetTop+"px"}(e,t),c?function(e,t){e.style.top=t+"px"}(e,a):de(e)}),Object(g.a)(([e])=>e),Object(P.a)(()=>{de(e),function(e){e.firstElementChild.style.height=""}(e)}))}var he=c(66);c(45);function me(e){return e.split(/"([^"]+)"/g).map((e,t)=>1&t?e.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):e).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim()}var ge=c(20);function ve(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const c of t)ve(e,c)}function $e(e,t,...c){const a=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?a.setAttribute(e,t[e]):t[e]&&a.setAttribute(e,"");for(const e of c)ve(a,e);return a}let ye;function we(e,t){if(void 0===ye){const e=S("#__lang");ye=JSON.parse(e.textContent)}if(void 0===ye[e])throw new ReferenceError("Invalid translation: "+e);return void 0!==t?ye[e].replace("#",t.toString()):ye[e]}function xe(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}var Ee;function Se(e){return e.type===Ee.READY}function ke(e){return e.type===Ee.QUERY}function _e(e){return e.type===Ee.RESULT}function Ae({config:e,docs:t,index:c}){1===e.lang.length&&"en"===e.lang[0]&&(e.lang=[we("search.config.lang")]),"[\\s\\-]+"===e.separator&&(e.separator=we("search.config.separator"));return{config:e,docs:t,index:c,pipeline:we("search.config.pipeline").split(/\s*,\s*/).filter(Boolean)}}function Te(e,{index$:t,base$:c}){const a=new Worker(e),n=new z.a,r=function(e,{tx$:t}){const c=Object(b.a)(e,"message").pipe(Object(g.a)(({data:e})=>e));return t.pipe(Object(ce.a)(()=>c,{leading:!0,trailing:!0}),Object(d.a)(t=>e.postMessage(t)),Object(ae.a)(c),Object(I.a)())}(a,{tx$:n}).pipe(Object(j.a)(c),Object(g.a)(([e,t])=>{if(_e(e))for(const c of e.data)for(const e of c)e.location=`${t}/${e.location}`;return e}),Object(I.a)());return t.pipe(Object(g.a)(e=>({type:Ee.SETUP,data:Ae(e)})),Object(h.a)(ge.b)).subscribe(n.next.bind(n)),{tx$:n,rx$:r}}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(Ee||(Ee={}));var Ce,Me=c(37);function Re(e,t){const c=t&Ce.PARENT,a=t&Ce.TEASER,n=Object.keys(e.terms).filter(t=>!e.terms[t]).map(e=>[$e("del",null,e)," "]).flat().slice(0,-1);return $e("a",{href:e.location,class:"md-search-result__link",tabIndex:-1},$e("article",{class:["md-search-result__article",...c?["md-search-result__article--document"]:[]].join(" "),"data-md-score":e.score.toFixed(2)},c>0&&$e("div",{class:"md-search-result__icon md-icon"}),$e("h1",{class:"md-search-result__title"},e.title),a>0&&e.text.length>0&&$e("p",{class:"md-search-result__teaser"},function(e,t){let c=t;if(e.length>c){for(;" "!==e[c]&&--c>0;);return e.substring(0,c)+"..."}return e}(e.text,320)),a>0&&n.length>0&&$e("p",{class:"md-search-result__terms"},we("search.result.term.missing"),": ",n)))}function Le(e,t=1/0){const c=[...e],a=c.findIndex(e=>!e.location.includes("#")),[n]=c.splice(a,1);let r=c.findIndex(e=>e.scoreRe(e,Ce.TEASER)),...i.length?[$e("details",{class:"md-search-result__more"},$e("summary",{tabIndex:-1},i.length>0&&1===i.length?we("search.result.more.one"):we("search.result.more.other",i.length)),i.map(e=>Re(e,Ce.TEASER)))]:[]];return $e("li",{class:"md-search-result__item"},s)}function ze(e){return $e("ul",{class:"md-source__facts"},e.map(e=>$e("li",{class:"md-source__fact"},e)))}function Pe({document$:e,dialog$:t}){if(!Me.isSupported())return o.a;e.subscribe(()=>{_("pre > code").forEach((e,t)=>{const c=e.parentElement;var a;c.id="__code_"+t,c.insertBefore((a=c.id,$e("button",{class:"md-clipboard md-icon",title:we("clipboard.copy"),"data-clipboard-target":`#${a} > code`})),e)})});const c=new W.a(e=>{new Me(".md-clipboard").on("success",t=>e.next(t))}).pipe(Object(I.a)());return c.pipe(Object(d.a)(e=>e.clearSelection()),Object(x.a)(we("clipboard.copied"))).subscribe(t),c}!function(e){e[e.TEASER=1]="TEASER",e[e.PARENT=2]="PARENT"}(Ce||(Ce={}));var Ue=c(67),He=c(79);function qe(e,{document$:t,viewport$:c,location$:a}){"scrollRestoration"in history&&(history.scrollRestoration="manual"),Object(b.a)(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"});const i=E('link[rel="shortcut icon"]');void 0!==i&&(i.href=i.href);const s=Object(b.a)(document.body,"click").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(f.a)(t=>{if(t.target instanceof HTMLElement){const c=t.target.closest("a");if(c&&!c.target&&D(c)&&e.includes(c.href))return Y(c)||t.preventDefault(),Object(r.a)(c)}return o.a}),Object(g.a)(e=>({url:new URL(e.href)})),Object(I.a)());s.subscribe(()=>{X("search",!1)});const p=s.pipe(Object(m.a)(({url:e})=>!Y(e)),Object(I.a)()),d=Object(b.a)(window,"popstate").pipe(Object(m.a)(e=>null!==e.state),Object(g.a)(e=>({url:new URL(location.href),offset:e.state})),Object(I.a)());Object(u.a)(p,d).pipe(Object(oe.a)((e,t)=>e.url.href===t.url.href),Object(g.a)(({url:e})=>e)).subscribe(a);const O=a.pipe(Object($.a)("pathname"),Object(Ue.a)(1),Object(f.a)(e=>Object(n.a)(fetch(e.href,{credentials:"same-origin"}).then(e=>e.text())).pipe(Object(l.a)(()=>(function(e){location.href=e.href}(e),o.a)))),Object(I.a)());p.pipe(Object(he.a)(O)).subscribe(({url:e})=>{history.pushState({},"",e.toString())});const j=new DOMParser;O.pipe(Object(g.a)(e=>j.parseFromString(e,"text/html"))).subscribe(t);Object(u.a)(p,d).pipe(Object(he.a)(t)).subscribe(({url:e,offset:t})=>{e.hash&&!t?K(e.hash):Z(t||{y:0})}),t.pipe(Object(Ue.a)(1)).subscribe(({title:e,head:t})=>{document.title=e;for(const e of['link[rel="canonical"]','meta[name="author"]','meta[name="description"]']){const c=E(e,t),a=E(e,document.head);void 0!==c&&void 0!==a&&T(a,c)}document.dispatchEvent(new CustomEvent("DOMContentSwitch"))}),c.pipe(Object(He.a)(250),Object($.a)("offset")).subscribe(({offset:e})=>{history.replaceState(e,"")}),Object(u.a)(s,d).pipe(Object(v.a)(2,1),Object(m.a)(([e,t])=>e.url.pathname===t.url.pathname&&!Y(t.url)),Object(g.a)(([,e])=>e)).subscribe(({offset:e})=>{Z(e||{y:0})})}function Ie(){const e=Object(b.a)(window,"keydown").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(g.a)(e=>({type:e.key,claim(){e.preventDefault(),e.stopPropagation()}})),Object(I.a)()).pipe(Object(g.a)(e=>{return Object.assign({mode:(t="search",Q[t].checked?"search":"global")},e);var t}),Object(m.a)(({mode:e})=>{if("global"===e){const e=k();if(void 0!==e)return!function(e){switch(e.tagName){case"INPUT":case"SELECT":case"TEXTAREA":return!0;default:return e.isContentEditable}}(e)}return!0}),Object(I.a)());return e.pipe(Object(m.a)(({mode:e})=>"search"===e),Object(j.a)(se("search-query"),se("search-result"))).subscribe(([e,t,c])=>{const a=k();switch(e.type){case"Enter":a===t&&e.claim();break;case"Escape":case"Tab":X("search",!1),M(t,!1);break;case"ArrowUp":case"ArrowDown":if(void 0===a)M(t);else{const n=[t,..._(":not(details) > [href], summary, details[open] [href]",c)],r=Math.max(0,(Math.max(0,n.indexOf(a))+n.length+("ArrowUp"===e.type?-1:1))%n.length);M(n[r])}e.claim();break;default:t!==k()&&M(t)}}),e.pipe(Object(m.a)(({mode:e})=>"global"===e),Object(j.a)(se("search-query"))).subscribe(([e,t])=>{switch(e.type){case"f":case"s":case"/":M(t),function(e){if(!(e instanceof HTMLInputElement))throw new Error("Not implemented");e.select()}(t),e.claim();break;case"p":case",":const c=E("[href][rel=prev]");void 0!==c&&c.click();break;case"n":case".":const a=E("[href][rel=next]");void 0!==a&&a.click()}}),e}function Ne(e){e.placeholder=we("search.placeholder")}function De(e,{transform:t}={}){const c=t||me,a=Object(u.a)(Object(b.a)(e,"keyup"),Object(b.a)(e,"focus").pipe(Object(O.a)(1))).pipe(Object(g.a)(()=>c(e.value)),Object(C.a)(c(e.value)),Object(oe.a)()),n=function(e){return Object(u.a)(Object(b.a)(e,"focus"),Object(b.a)(e,"blur")).pipe(Object(g.a)(({type:e})=>"focus"===e),Object(C.a)(e===k()))}(e);return Object(i.a)([a,n]).pipe(Object(g.a)(([e,t])=>({value:e,focus:t})))}function Ye({tx$:e},t={}){return Object(be.a)(Object(f.a)(c=>{const a=De(c,t);return a.pipe(Object($.a)("value"),Object(g.a)(({value:e})=>({type:Ee.QUERY,data:e}))).subscribe(e.next.bind(e)),a.pipe(Object($.a)("focus")).subscribe(({focus:e})=>{e&&X("search",e)}),a.pipe(function(e){return Object(be.a)(Object(d.a)(({focus:t})=>{t?function(e,t){e.placeholder=t}(e,""):Ne(e)}),Object(P.a)(()=>{Ne(e)}))}(c))}))}function Fe(){return Object(be.a)(Object(f.a)(e=>function(e){return Object(b.a)(e,"click").pipe(Object(x.a)(void 0))}(e).pipe(Object(ae.a)(se("search-query")),Object(d.a)(M),Object(x.a)(void 0))),Object(C.a)(void 0))}function Je(e,t){e.appendChild(t)}function Ke(e,{query$:t,ready$:c,fetch$:a}){const n=S(".md-search-result__list",e),r=S(".md-search-result__meta",e);return Object(be.a)(Object(j.a)(t,c),Object(g.a)(([e,t])=>(t.value?function(e,t){switch(t){case 0:e.textContent=we("search.result.none");break;case 1:e.textContent=we("search.result.one");break;default:e.textContent=we("search.result.other",t)}}(r,e.length):function(e){e.textContent=we("search.result.placeholder")}(r),e)),Object(f.a)(t=>{const c=[...t.map(([e])=>e.score),0];return a.pipe(Object(h.a)(s.a),Object(re.a)(a=>{const r=e.parentElement;for(;a16)););return a},0),Object(x.a)(t),Object(P.a)(()=>{!function(e){e.innerHTML=""}(n)}))}))}function We({rx$:e},{query$:t}){return Object(be.a)(Object(f.a)(c=>{const a=c.parentElement,n=e.pipe(Object(m.a)(Se),Object(x.a)(!0)),r=function(e){return Object(u.a)(Object(b.a)(e,"scroll"),Object(b.a)(window,"resize")).pipe(Object(g.a)(()=>R(e)),Object(C.a)(R(e)))}(a).pipe(Object(g.a)(({y:e})=>e>=a.scrollHeight-a.offsetHeight-16),Object(oe.a)(),Object(m.a)(Boolean));return e.pipe(Object(m.a)(_e),Object(g.a)(({data:e})=>e),Ke(c,{query$:t,ready$:n,fetch$:r}),Object(C.a)([]))}))}function Be({header$:e,viewport$:t,screen$:c}){return Object(be.a)(Object(f.a)(a=>c.pipe(Object(f.a)(c=>c?te(a,{header$:e,viewport$:t}).pipe(Object(g.a)(({offset:{y:e}})=>({hidden:e>=10})),Object($.a)("hidden"),function(e){return Object(be.a)(Object(h.a)(s.a),Object(d.a)(({hidden:t})=>{!function(e,t){e.setAttribute("data-md-state",t?"hidden":"")}(e,t)}),Object(P.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(e)}))}(a)):Object(r.a)({hidden:!0})))))}function Qe(e){e.removeAttribute("data-md-state")}function Xe(e){e.classList.remove("md-nav__link--active")}function Ve({header$:e,main$:t,viewport$:c,tablet$:a}){return Object(be.a)(Object(f.a)(n=>a.pipe(Object(f.a)(a=>{if(a){const a=_(".md-nav__link",n),r=Oe(n,{main$:t,viewport$:c}).pipe(je(n,{header$:e})),o=function(e,{header$:t,viewport$:c}){const a=new Map;for(const t of e){const e=E(`[id="${decodeURIComponent(t.hash.substring(1))}"]`);void 0!==e&&a.set(t,e)}const n=t.pipe(Object(g.a)(e=>18+e.height));return q(document.body).pipe(Object($.a)("height"),Object(g.a)(()=>{let e=[];return[...a].reduce((t,[c,n])=>{for(;e.length;){if(!(a.get(e[e.length-1]).tagName>=n.tagName))break;e.pop()}let r=n.offsetTop;for(;!r&&n.parentElement;)r=(n=n.parentElement).offsetTop;return t.set([...e=[...e,c]].reverse(),r)},new Map)}),Object(f.a)(e=>Object(i.a)([n,c]).pipe(Object(re.a)(([e,t],[c,{offset:{y:a}}])=>{for(;t.length;){const[,n]=t[0];if(!(n-c=a))break;t=[e.pop(),...t]}return[e,t]},[[],[...e]]),Object(oe.a)((e,t)=>e[0]===t[0]&&e[1]===t[1])))).pipe(Object(g.a)(([e,t])=>({prev:e.map(([e])=>e),next:t.map(([e])=>e)})),Object(C.a)({prev:[],next:[]}),Object(v.a)(2,1),Object(g.a)(([e,t])=>e.prev.length{for(const[e]of t)Xe(e),Qe(e);e.forEach(([t],c)=>{!function(e,t){e.classList.toggle("md-nav__link--active",t)}(t,c===e.length-1),function(e,t){e.setAttribute("data-md-state",t?"blur":"")}(t,!0)})}),Object(P.a)(()=>{for(const t of e)Xe(t),Qe(t)}))}(a));return Object(i.a)([r,o]).pipe(Object(g.a)(([e,t])=>({sidebar:e,anchors:t})))}return Object(r.a)({})}))))}var Ge=c(70);var Ze=c(71);function et(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}var tt=c(72);function ct(e){const[t]=e.match(/(git(?:hub|lab))/i)||[];switch(t.toLowerCase()){case"github":const[,t,c]=e.match(/^.+github\.com\/([^\/]+)\/?([^\/]+)?/i);return function(e,t){const c=void 0!==t?`https://api.github.com/repos/${e}/${t}`:"https://api.github.com/users/"+e;return Object(n.a)(fetch(c)).pipe(Object(m.a)(e=>200===e.status),Object(f.a)(e=>e.json()),Object(g.a)(e=>{if(void 0!==t){const{stargazers_count:t,forks_count:c}=e;return[xe(t)+" Stars",xe(c)+" Forks"]}{const{public_repos:t}=e;return[xe(t)+" Repositories"]}}),Object(tt.a)([]),Object(I.a)())}(t,c);case"gitlab":const[,a,r]=e.match(/^.+?([^\/]*gitlab[^\/]+)\/(.+?)\/?$/i);return function(e,t){const c=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return Object(n.a)(fetch(c)).pipe(Object(m.a)(e=>200===e.status),Object(f.a)(e=>e.json()),Object(g.a)(({star_count:e,forks_count:t})=>[xe(e)+" Stars",xe(t)+" Forks"]),Object(tt.a)([]),Object(I.a)())}(a,r);default:return o.a}}function at({document$:e}){e.pipe(Object(g.a)(()=>S(".md-source[href]")),Object(f.a)(({href:e})=>{return t=""+function(e){let t=0;for(let c=0,a=e.length;cct(e),Object(a.a)(()=>{const e=sessionStorage.getItem(t);if(e)return Object(r.a)(JSON.parse(e));{const e=c();return e.subscribe(e=>{try{sessionStorage.setItem(t,JSON.stringify(e))}catch(e){}}),e}});var t,c}),Object(m.a)(e=>e.length>0),Object(l.a)(()=>o.a)).subscribe(e=>{for(const t of _(".md-source__repository"))t.hasAttribute("data-md-state")||(t.setAttribute("data-md-state","done"),t.appendChild(ze(e)))})}function nt(e,t){e.setAttribute("data-md-state","lock"),e.style.top=`-${t}px`}function rt(e){const t=-1*parseInt(e.style.top,10);e.removeAttribute("data-md-state"),e.style.top="",t&&window.scrollTo(0,t)}function ot(e){if(!function(e){return"object"==typeof e&&"string"==typeof e.base&&"object"==typeof e.features&&"object"==typeof e.search}(e))throw new SyntaxError("Invalid configuration: "+JSON.stringify(e));const t=function(){const e=new w.a;return Object(b.a)(document,"DOMContentLoaded").pipe(Object(x.a)(document)).subscribe(e),e}(),c=F(),S=function(e,{location$:t}){return t.pipe(Object(y.a)(1),Object(g.a)(({href:t})=>new URL(e,t).toString().replace(/\/$/,"")),Object(p.a)({bufferSize:1,refCount:!0}))}(e.base,{location$:c}),k=Object(b.a)(window,"hashchange").pipe(Object(g.a)(J),Object(C.a)(J()),Object(m.a)(e=>e.length>0),Object(I.a)()),M=Object(i.a)([Object(u.a)(Object(b.a)(window,"scroll",{passive:!0}),Object(b.a)(window,"resize",{passive:!0})).pipe(Object(g.a)(G),Object(C.a)(G())),Object(b.a)(window,"resize",{passive:!0}).pipe(Object(g.a)(ee),Object(C.a)(ee()))]).pipe(Object(g.a)(([e,t])=>({offset:e,size:t})),Object(p.a)({bufferSize:1,refCount:!0})),R=B("(min-width: 960px)"),L=B("(min-width: 1220px)");!function(e,{document$:t}){ie=t.pipe(Object(g.a)(t=>e.reduce((e,c)=>{const a=E(`[data-md-component=${c}]`,t);return Object.assign(Object.assign({},e),void 0!==a?{[c]:a}:{})},{})),Object(re.a)((t,c)=>{for(const a of e)switch(a){case"announce":case"header-title":case"container":case"skip":a in t&&void 0!==t[a]&&(T(t[a],c[a]),t[a]=c[a]);break;default:void 0!==c[a]?t[a]=E(`[data-md-component=${a}]`):delete t[a]}return t}),Object(p.a)({bufferSize:1,refCount:!0}))}(["announce","container","header","header-title","main","navigation","search","search-query","search-reset","search-result","skip","tabs","toc"],{document$:t});const P=Ie();matchMedia("(hover)").matches&&function({document$:e,viewport$:t}){const c=e.pipe(Object(g.a)(()=>_("pre > code"))),a=t.pipe(Object($.a)("size"));Object(i.a)([c,a]).subscribe(([e])=>{for(const t of e)t.scrollWidth>t.clientWidth?t.setAttribute("tabindex","0"):t.removeAttribute("tabindex")})}({document$:t,viewport$:M}),function({document$:e,hash$:t}){const c=e.pipe(Object(g.a)(()=>_("details")));Object(u.a)(B("print").pipe(Object(m.a)(Boolean)),Object(b.a)(window,"beforeprint")).pipe(Object(ae.a)(c)).subscribe(e=>{for(const t of e)t.setAttribute("open","")}),t.pipe(Object(g.a)(e=>E(`[id="${e}"]`)),Object(m.a)(e=>void 0!==e),Object(d.a)(e=>{const t=e.closest("details");t&&!t.open&&t.setAttribute("open","")})).subscribe(e=>e.scrollIntoView())}({document$:t,hash$:k}),function({document$:e}){e.pipe(Object(Ue.a)(1),Object(j.a)(se("container")),Object(g.a)(([,e])=>_("script",e))).pipe(Object(f.a)(e=>Object(r.a)(...e)),Object(Ge.a)(e=>{const t=A("script");return e.src?(t.src=e.src,T(e,t),new W.a(e=>{t.onload=()=>e.complete()})):(t.textContent=e.textContent,T(e,t),ne.a)})).subscribe(fe.a)}({document$:t}),at({document$:t}),function({document$:e}){const t=A("table");e.pipe(Object(g.a)(()=>_("table:not([class])"))).subscribe(e=>{for(const c of e)T(c,t),T(t,$e("div",{class:"md-typeset__scrollwrap"},$e("div",{class:"md-typeset__table"},c)))})}({document$:t}),function({document$:e}){const t=e.pipe(Object(g.a)(()=>_("[data-md-scrollfix]")),Object(p.a)({bufferSize:1,refCount:!0}));t.subscribe(e=>{for(const t of e)t.removeAttribute("data-md-scrollfix")}),Object(Ze.a)(et,t,o.a).pipe(Object(f.a)(e=>Object(u.a)(...e.map(e=>Object(b.a)(e,"touchstart").pipe(Object(x.a)(e)))))).subscribe(e=>{const t=e.scrollTop;0===t?e.scrollTop=1:t+e.offsetHeight===e.scrollHeight&&(e.scrollTop=t-1)})}({document$:t});const U=function({duration:e}={}){const t=new z.a,c=A("div");return c.classList.add("md-dialog","md-typeset"),t.pipe(Object(f.a)(t=>Object(r.a)(document.body).pipe(Object(g.a)(e=>e.appendChild(c)),Object(h.a)(s.a),Object(O.a)(1),Object(d.a)(e=>{e.innerHTML=t,e.setAttribute("data-md-state","open")}),Object(O.a)(e||2e3),Object(d.a)(e=>e.removeAttribute("data-md-state")),Object(O.a)(400),Object(d.a)(e=>{e.innerHTML="",e.remove()})))).subscribe(fe.a),t}(),H=Pe({document$:t,dialog$:U}),q=se("header").pipe(pe({document$:t,viewport$:M}),Object(p.a)({bufferSize:1,refCount:!0})),N=se("main").pipe(le({header$:q,viewport$:M}),Object(p.a)({bufferSize:1,refCount:!0})),Y=se("navigation").pipe(function({header$:e,main$:t,viewport$:c,screen$:a}){return Object(be.a)(Object(f.a)(n=>a.pipe(Object(f.a)(a=>a?Oe(n,{main$:t,viewport$:c}).pipe(je(n,{header$:e}),Object(g.a)(e=>({sidebar:e}))):Object(r.a)({})))))}({header$:q,main$:N,viewport$:M,screen$:L}),Object(p.a)({bufferSize:1,refCount:!0})),Q=se("toc").pipe(Ve({header$:q,main$:N,viewport$:M,tablet$:R}),Object(p.a)({bufferSize:1,refCount:!0})),Z=se("tabs").pipe(Be({header$:q,viewport$:M,screen$:L}),Object(p.a)({bufferSize:1,refCount:!0})),te=se("search").pipe(Object(f.a)(()=>Object(a.a)(()=>{const t=e.search&&e.search.index?e.search.index:void 0,c=void 0!==t?Object(n.a)(t):S.pipe(Object(f.a)(e=>fetch(e+"/search/search_index.json",{credentials:"same-origin"}).then(e=>e.json())));return Object(r.a)(Te(e.search.worker,{base$:S,index$:c}))}))).pipe(Object(f.a)(t=>{const c=se("search-query").pipe(Ye(t,{transform:e.search.transform}),Object(p.a)({bufferSize:1,refCount:!0})),a=se("search-reset").pipe(Fe(),Object(p.a)({bufferSize:1,refCount:!0})),n=se("search-result").pipe(We(t,{query$:c}),Object(p.a)({bufferSize:1,refCount:!0}));return se("search").pipe(function({rx$:e,tx$:t},{query$:c,reset$:a,result$:n}){return Object(be.a)(Object(f.a)(()=>{const r=e.pipe(Object(m.a)(Se),Object(x.a)("ready"),Object(C.a)("waiting"));return t.pipe(Object(m.a)(ke),Object(he.a)(r),Object(y.a)(1)).subscribe(t.next.bind(t)),Object(i.a)([r,c,n,a]).pipe(Object(g.a)(([e,t,c])=>({status:e,query:t,result:c})))}))}(t,{query$:c,reset$:a,result$:n}))}),Object(l.a)(()=>(se("search").subscribe(e=>e.hidden=!0),o.a)),Object(p.a)({bufferSize:1,refCount:!0}));if(k.pipe(Object(d.a)(()=>X("search",!1)),Object(O.a)(125)).subscribe(e=>K("#"+e)),Object(i.a)([V("search"),R]).pipe(Object(j.a)(M),Object(f.a)(([[e,c],{offset:{y:a}}])=>{const n=e&&!c;return t.pipe(Object(O.a)(n?400:100),Object(h.a)(s.a),Object(d.a)(({body:e})=>n?nt(e,a):rt(e)))})).subscribe(),Object(b.a)(document.body,"click").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(m.a)(e=>{if(e.target instanceof HTMLElement){const t=e.target.closest("a");if(t&&D(t))return!0}return!1})).subscribe(()=>{X("drawer",!1)}),e.features.includes("navigation.instant")&&"file:"!==location.protocol){const e=new DOMParser;S.pipe(Object(f.a)(t=>Object(n.a)(fetch(t+"/sitemap.xml").then(e=>e.text()).then(t=>e.parseFromString(t,"text/xml")))),Object(j.a)(S),Object(g.a)(([e,t])=>{const c=_("loc",e).map(e=>e.textContent);if(c.length>1){const[e,a]=c.sort((e,t)=>e.length-t.length);let n=0;if(e===a)n=e.length;else for(;e.charAt(n)===a.charAt(n);)n++;for(let a=0;a{qe(e,{document$:t,location$:c,viewport$:M})})}t.subscribe(()=>{const e=_("[data-md-state=indeterminate]");for(const t of e)t.dataset.mdState="",t.indeterminate=!0,t.checked=!1}),e.features.includes("header.autohide")&&M.pipe(Object(g.a)(({offset:e})=>e.y),Object(v.a)(2,1),Object(g.a)(([e,t])=>[eM.pipe(Object(g.a)(({offset:e})=>e.y),Object(m.a)(e=>e>400),Object(g.a)(e=>Math.abs(t-e)),Object(m.a)(e=>e>100),Object(g.a)(()=>e),Object(y.a)(1)))).subscribe(e=>{const t=E("[data-md-component=header]");null==t||t.setAttribute("data-md-state",e?"hidden":"shadow")});const ce={document$:t,location$:c,viewport$:M,header$:q,main$:N,navigation$:Y,search$:te,tabs$:Z,toc$:Q,clipboard$:H,keyboard$:P,dialog$:U};return Object(u.a)(...Object.values(ce)).subscribe(),ce}document.documentElement.classList.remove("no-js"),document.documentElement.classList.add("js"),navigator.userAgent.match(/(iPad|iPhone|iPod)/g)&&document.documentElement.classList.add("ios")}})); -//# sourceMappingURL=bundle.6ced434e.min.js.map \ No newline at end of file diff --git a/docs/assets/javascripts/bundle.6ced434e.min.js.map b/docs/assets/javascripts/bundle.6ced434e.min.js.map deleted file mode 100644 index 8f358c5..0000000 --- a/docs/assets/javascripts/bundle.6ced434e.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/assets/javascripts/browser/element/_/index.ts","webpack:///./src/assets/javascripts/browser/element/focus/index.ts","webpack:///./src/assets/javascripts/browser/element/offset/index.ts","webpack:///./src/assets/javascripts/browser/element/size/index.ts","webpack:///./src/assets/javascripts/browser/location/_/index.ts","webpack:///./src/assets/javascripts/browser/location/hash/index.ts","webpack:///./src/assets/javascripts/browser/media/index.ts","webpack:///./src/assets/javascripts/browser/toggle/index.ts","webpack:///./src/assets/javascripts/browser/viewport/offset/index.ts","webpack:///./src/assets/javascripts/browser/viewport/size/index.ts","webpack:///./src/assets/javascripts/browser/viewport/_/index.ts","webpack:///./src/assets/javascripts/components/_/index.ts","webpack:///./src/assets/javascripts/components/header/_/index.ts","webpack:///./src/assets/javascripts/components/header/react/index.ts","webpack:///./src/assets/javascripts/components/header/set/index.ts","webpack:///./src/assets/javascripts/components/main/_/index.ts","webpack:///./src/assets/javascripts/components/main/react/index.ts","webpack:///./src/assets/javascripts/components/main/set/index.ts","webpack:///./src/assets/javascripts/components/shared/sidebar/set/index.ts","webpack:///./src/assets/javascripts/components/shared/sidebar/react/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/transform/index.ts","webpack:///./src/assets/javascripts/utilities/jsx/index.ts","webpack:///./src/assets/javascripts/utilities/string/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/_/index.ts","webpack:///./src/assets/javascripts/browser/worker/index.ts","webpack:///./src/assets/javascripts/templates/search/index.tsx","webpack:///./src/assets/javascripts/templates/source/index.tsx","webpack:///./src/assets/javascripts/integrations/clipboard/index.ts","webpack:///./src/assets/javascripts/templates/clipboard/index.tsx","webpack:///./src/assets/javascripts/integrations/instant/index.ts","webpack:///./src/assets/javascripts/integrations/keyboard/index.ts","webpack:///./src/assets/javascripts/browser/keyboard/index.ts","webpack:///./src/assets/javascripts/browser/element/select/index.ts","webpack:///./src/assets/javascripts/components/search/query/set/index.ts","webpack:///./src/assets/javascripts/components/search/query/react/index.ts","webpack:///./src/assets/javascripts/components/search/query/_/index.ts","webpack:///./src/assets/javascripts/components/search/reset/_/index.ts","webpack:///./src/assets/javascripts/components/search/reset/react/index.ts","webpack:///./src/assets/javascripts/components/search/result/set/index.ts","webpack:///./src/assets/javascripts/components/search/result/react/index.ts","webpack:///./src/assets/javascripts/components/search/result/_/index.ts","webpack:///./src/assets/javascripts/components/tabs/_/index.ts","webpack:///./src/assets/javascripts/components/tabs/react/index.ts","webpack:///./src/assets/javascripts/components/tabs/set/index.ts","webpack:///./src/assets/javascripts/components/toc/anchor/set/index.ts","webpack:///./src/assets/javascripts/components/toc/_/index.ts","webpack:///./src/assets/javascripts/components/toc/anchor/react/index.ts","webpack:///./src/assets/javascripts/patches/scrollfix/index.ts","webpack:///./src/assets/javascripts/patches/source/index.ts","webpack:///./src/assets/javascripts/patches/source/github/index.ts","webpack:///./src/assets/javascripts/patches/source/gitlab/index.ts","webpack:///./src/assets/javascripts/utilities/rxjs/index.ts","webpack:///./src/assets/javascripts/index.ts","webpack:///./src/assets/javascripts/utilities/config/index.ts","webpack:///./src/assets/javascripts/browser/document/index.ts","webpack:///./src/assets/javascripts/browser/location/base/index.ts","webpack:///./src/assets/javascripts/patches/code/index.ts","webpack:///./src/assets/javascripts/patches/details/index.ts","webpack:///./src/assets/javascripts/patches/script/index.ts","webpack:///./src/assets/javascripts/patches/table/index.ts","webpack:///./src/assets/javascripts/templates/table/index.tsx","webpack:///./src/assets/javascripts/integrations/dialog/index.ts","webpack:///./src/assets/javascripts/components/navigation/index.ts","webpack:///./src/assets/javascripts/components/search/_/index.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","getActiveElement","activeElement","HTMLElement","getElements","Array","from","querySelectorAll","createElement","tagName","replaceElement","source","target","replaceWith","setElementFocus","focus","blur","getElementOffset","x","scrollLeft","y","scrollTop","entry$","Subject","observer$","defer","of","entries","entry","next","pipe","switchMap","resize","merge","finalize","disconnect","shareReplay","bufferSize","refCount","watchElementSize","tap","observer","observe","filter","unobserve","map","contentRect","width","height","startWith","offsetWidth","offsetHeight","getElementSize","isLocalLocation","url","ref","location","host","test","pathname","isAnchorLocation","hash","watchLocation","BehaviorSubject","URL","href","getLocationHash","substring","setLocationHash","addEventListener","ev","stopPropagation","click","watchMedia","query","media","matchMedia","Observable","subscriber","addListener","matches","drawer","search","setToggle","checked","watchToggle","fromEvent","getViewportOffset","Math","max","pageXOffset","pageYOffset","setViewportOffset","scrollTo","getViewportSize","innerWidth","innerHeight","watchViewportAt","header$","viewport$","size$","distinctUntilKeyChanged","offset$","combineLatest","offsetLeft","offsetTop","offset","size","components$","useComponent","components","distinctUntilChanged","mountHeader","document$","styles","getComputedStyle","includes","position","sticky","watchHeader","type$","main","hx","zipWith","title","observeOn","animationFrame","type","setAttribute","setHeaderTitleActive","removeAttribute","resetHeaderTitleActive","applyHeaderType","header","mountMain","main$","active","setHeaderShadow","resetHeaderShadow","subscribe","noop","adjust$","border$","top","bottom","a","b","watchMain","complete","resetSidebarOffset","style","watchSidebar","adjust","parentElement","min","lock","applySidebar","withLatestFrom","scrollwrap","firstElementChild","setSidebarHeight","setSidebarOffset","sidebar","resetSidebarHeight","defaultTransform","split","terms","index","replace","join","trim","appendChild","child","innerHTML","toString","Node","isArray","h","tag","attributes","children","attr","keys","lang","translate","JSON","parse","textContent","round","toFixed","SearchMessageType","isSearchReadyMessage","message","READY","isSearchQueryMessage","QUERY","isSearchResultMessage","RESULT","setupSearchIndex","config","docs","separator","pipeline","Boolean","setupSearchWorker","index$","base$","worker","Worker","tx$","rx$","throttle","leading","trailing","postMessage","switchMapTo","share","watchWorker","base","SETUP","Flag","renderSearchDocument","flag","parent","PARENT","teaser","TEASER","missing","flat","class","tabIndex","score","text","truncate","renderSearchResult","threshold","Infinity","findIndex","doc","article","best","more","section","renderSource","facts","fact","setupClipboard","dialog$","forEach","block","id","insertBefore","clipboard$","on","clearSelection","mapTo","setupInstantLoading","urls","location$","history","scrollRestoration","favicon","state$","body","metaKey","ctrlKey","closest","preventDefault","push$","pop$","state","prev","ajax$","skip","fetch","credentials","then","res","catchError","setLocation","sample","pushState","dom","DOMParser","response","parseFromString","head","dispatchEvent","CustomEvent","debounceTime","replaceState","bufferCount","setupKeyboard","keyboard$","isContentEditable","isSusceptibleToKeyboard","claim","els","indexOf","HTMLInputElement","Error","select","setElementSelection","resetSearchQueryPlaceholder","placeholder","watchSearchQuery","transform","fn","value$","delay","focus$","watchElementFocus","mountSearchQuery","options","query$","setSearchQueryPlaceholder","applySearchQuery","mountSearchReset","watchSearchReset","addToSearchResultList","applySearchResult","ready$","fetch$","list","meta","setSearchResultMeta","resetSearchResultMeta","thresholds","scan","container","scrollHeight","resetSearchResultList","mountSearchResult","watchElementOffset","mountTabs","screen$","screen","hidden","setTabsHidden","resetTabsHidden","applyTabs","resetAnchorBlur","resetAnchorActive","classList","remove","mountTableOfContents","tablet$","tablet","sidebar$","anchors$","table","Map","decodeURIComponent","set","path","reduce","anchor","pop","reverse","watchAnchorList","toggle","setAnchorActive","setAnchorBlur","applyAnchorList","anchors","isAppleDevice","navigator","userAgent","fetchSourceFacts","match","toLowerCase","user","repo","status","json","stargazers_count","forks_count","public_repos","defaultIfEmpty","fetchSourceFactsFromGitHub","slug","project","encodeURIComponent","star_count","fetchSourceFactsFromGitLab","patchSource","len","charCodeAt","factory","sessionStorage","getItem","setItem","stringify","err","hasAttribute","setScrollLock","resetScrollLock","parseInt","initialize","features","isConfig","SyntaxError","ReplaySubject","watchDocument","take","watchLocationBase","hash$","passive","names","setupComponents","els$","scrollWidth","clientWidth","patchCodeBlocks","details","open","scrollIntoView","patchDetails","concatMap","script","src","onload","patchScripts","sentinel","patchTables","iif","patchScrollfix","duration","dialog","add","setupDialog","navigation$","mountNavigation","toc$","tabs$","search$","reset$","result$","status$","mountSearch","protocol","sort","charAt","toggles","dataset","mdState","indeterminate","direction","y0","y1","abs","hide","values","documentElement"],"mappings":"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","file":"assets/javascripts/bundle.6ced434e.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \tvar deferredModules = [];\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 \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([51,1]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Element or nothing\n */\nexport function getElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Element\n */\nexport function getElementOrThrow(\n selector: string, node: ParentNode = document\n): T {\n const el = getElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n return el\n}\n\n/**\n * Retrieve the currently active element\n *\n * @return Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement\n : undefined\n}\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Elements\n */\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @template T - Tag name type\n *\n * @param tagName - Tag name\n *\n * @return Element\n */\nexport function createElement(\n tagName: T\n): HTMLElementTagNameMap[T] {\n return document.createElement(tagName)\n}\n\n/**\n * Replace an element with another element\n *\n * @param source - Source element\n * @param target - Target element\n */\nexport function replaceElement(\n source: HTMLElement, target: Node\n): void {\n source.replaceWith(target)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getActiveElement } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element focus\n *\n * @param el - Element\n * @param value - Whether the element should be focused\n */\nexport function setElementFocus(\n el: HTMLElement, value: boolean = true\n): void {\n if (value)\n el.focus()\n else\n el.blur()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element focus\n *\n * @param el - Element\n *\n * @return Element focus observable\n */\nexport function watchElementFocus(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"focus\"),\n fromEvent(el, \"blur\")\n )\n .pipe(\n map(({ type }) => type === \"focus\"),\n startWith(el === getActiveElement())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element offset\n *\n * @param el - Element\n *\n * @return Element offset\n */\nexport function getElementOffset(el: HTMLElement): ElementOffset {\n return {\n x: el.scrollLeft,\n y: el.scrollTop\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element offset\n *\n * @param el - Element\n *\n * @return Element offset observable\n */\nexport function watchElementOffset(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"scroll\"),\n fromEvent(window, \"resize\")\n )\n .pipe(\n map(() => getElementOffset(el)),\n startWith(getElementOffset(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ResizeObserver from \"resize-observer-polyfill\"\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n merge,\n of\n} from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(resize => merge(of(resize), NEVER)\n .pipe(\n finalize(() => resize.disconnect())\n )\n ),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @return Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that will subscribe to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * @param el - Element\n *\n * @return Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ contentRect }) => ({\n width: contentRect.width,\n height: contentRect.height\n }))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { BehaviorSubject, Subject } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location\n *\n * This function will return a `URL` object (and not `Location`) in order to\n * normalize typings across the application. Furthermore, locations need to be\n * tracked without setting them and `Location` is a singleton which represents\n * the current location.\n *\n * @return URL\n */\nexport function getLocation(): URL {\n return new URL(location.href)\n}\n\n/**\n * Set location\n *\n * @param url - URL to change to\n */\nexport function setLocation(url: URL): void {\n location.href = url.href\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Check whether a URL is a local link or a file (except `.html`)\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isLocalLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.host === ref.host\n && /^(?:\\/[\\w-]+)*(?:\\/?|\\.html)$/i.test(url.pathname)\n}\n\n/**\n * Check whether a URL is an anchor link on the current page\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isAnchorLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.pathname === ref.pathname\n && url.hash.length > 0\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @return Location subject\n */\nexport function watchLocation(): Subject {\n return new BehaviorSubject(getLocation())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { filter, map, share, startWith } from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @return Location hash\n */\nexport function getLocationHash(): string {\n return location.hash.substring(1)\n}\n\n/**\n * Set location hash\n *\n * Setting a new fragment identifier via `location.hash` will have no effect\n * if the value doesn't change. When a new fragment identifier is set, we want\n * the browser to target the respective element at all times, which is why we\n * use this dirty little trick.\n *\n * @param hash - Location hash\n */\nexport function setLocationHash(hash: string): void {\n const el = createElement(\"a\")\n el.href = hash\n el.addEventListener(\"click\", ev => ev.stopPropagation())\n el.click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location hash\n *\n * @return Location hash observable\n */\nexport function watchLocationHash(): Observable {\n return fromEvent(window, \"hashchange\")\n .pipe(\n map(getLocationHash),\n startWith(getLocationHash()),\n filter(hash => hash.length > 0),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { shareReplay, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * @param query - Media query\n *\n * @return Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return new Observable(subscriber => {\n media.addListener(ev => subscriber.next(ev.matches))\n })\n .pipe(\n startWith(media.matches),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElementOrThrow(`[data-md-toggle=drawer]`),\n search: getElementOrThrow(`[data-md-toggle=search]`)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @return Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @return Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport offset\n */\nexport interface ViewportOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport offset\n *\n * On iOS Safari, viewport offset can be negative due to overflow scrolling.\n * As this may induce strange behaviors downstream, we'll just limit it to 0.\n *\n * @return Viewport offset\n */\nexport function getViewportOffset(): ViewportOffset {\n return {\n x: Math.max(0, pageXOffset),\n y: Math.max(0, pageYOffset)\n }\n}\n\n/**\n * Set viewport offset\n *\n * @param offset - Viewport offset\n */\nexport function setViewportOffset(\n { x, y }: Partial\n): void {\n window.scrollTo(x || 0, y || 0)\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport offset\n *\n * @return Viewport offset observable\n */\nexport function watchViewportOffset(): Observable {\n return merge(\n fromEvent(window, \"scroll\", { passive: true }),\n fromEvent(window, \"resize\", { passive: true })\n )\n .pipe(\n map(getViewportOffset),\n startWith(getViewportOffset())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport size\n */\nexport interface ViewportSize {\n width: number /* Viewport width */\n height: number /* Viewport height */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport size\n *\n * @return Viewport size\n */\nexport function getViewportSize(): ViewportSize {\n return {\n width: innerWidth,\n height: innerHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport size\n *\n * @return Viewport size observable\n */\nexport function watchViewportSize(): Observable {\n return fromEvent(window, \"resize\", { passive: true })\n .pipe(\n map(getViewportSize),\n startWith(getViewportSize())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n shareReplay\n} from \"rxjs/operators\"\n\nimport { Header } from \"components\"\n\nimport {\n ViewportOffset,\n watchViewportOffset\n} from \"../offset\"\nimport {\n ViewportSize,\n watchViewportSize\n} from \"../size\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport\n */\nexport interface Viewport {\n offset: ViewportOffset /* Viewport offset */\n size: ViewportSize /* Viewport size */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch at options\n */\ninterface WatchAtOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @return Viewport observable\n */\nexport function watchViewport(): Observable {\n return combineLatest([\n watchViewportOffset(),\n watchViewportSize()\n ])\n .pipe(\n map(([offset, size]) => ({ offset, size })),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/**\n * Watch viewport relative to element\n *\n * @param el - Element\n * @param options - Options\n *\n * @return Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { header$, viewport$ }: WatchAtOptions\n): Observable {\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Compute element offset */\n const offset$ = combineLatest([size$, header$])\n .pipe(\n map((): ViewportOffset => ({\n x: el.offsetLeft,\n y: el.offsetTop\n }))\n )\n\n /* Compute relative viewport, return hot observable */\n return combineLatest([header$, viewport$, offset$])\n .pipe(\n map(([{ height }, { offset, size }, { x, y }]) => ({\n offset: {\n x: offset.x - x,\n y: offset.y - y + height\n },\n size\n }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { EMPTY, Observable, of } from \"rxjs\"\nimport {\n distinctUntilChanged,\n map,\n scan,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\nimport { getElement, replaceElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Component\n */\nexport type Component =\n | \"announce\" /* Announcement bar */\n | \"container\" /* Container */\n | \"header\" /* Header */\n | \"header-title\" /* Header title */\n | \"main\" /* Main area */\n | \"navigation\" /* Navigation */\n | \"search\" /* Search */\n | \"search-query\" /* Search input */\n | \"search-reset\" /* Search reset */\n | \"search-result\" /* Search results */\n | \"skip\" /* Skip link */\n | \"tabs\" /* Tabs */\n | \"toc\" /* Table of contents */\n\n/**\n * Component map\n */\nexport type ComponentMap = {\n [P in Component]?: HTMLElement\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Component map observable\n */\nlet components$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up bindings to components with given names\n *\n * This function will maintain bindings to the elements identified by the given\n * names in-between document switches and update the elements in-place.\n *\n * @param names - Component names\n * @param options - Options\n */\nexport function setupComponents(\n names: Component[], { document$ }: WatchOptions\n): void {\n components$ = document$\n .pipe(\n\n /* Build component map */\n map(document => names.reduce((components, name) => {\n const el = getElement(`[data-md-component=${name}]`, document)\n return {\n ...components,\n ...typeof el !== \"undefined\" ? { [name]: el } : {}\n }\n }, {})),\n\n /* Re-compute component map on document switch */\n scan((prev, next) => {\n for (const name of names) {\n switch (name) {\n\n /* Top-level components: update */\n case \"announce\":\n case \"header-title\":\n case \"container\":\n case \"skip\":\n if (name in prev && typeof prev[name] !== \"undefined\") {\n replaceElement(prev[name]!, next[name]!)\n prev[name] = next[name]\n }\n break\n\n /* All other components: rebind */\n default:\n if (typeof next[name] !== \"undefined\")\n prev[name] = getElement(`[data-md-component=${name}]`)\n else\n delete prev[name]\n }\n }\n return prev\n }),\n\n /* Convert to hot observable */\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/**\n * Retrieve a component\n *\n * The returned observable will only re-emit if the element changed, i.e. if\n * it was replaced from a document which was switched to.\n *\n * @template T - Element type\n *\n * @param name - Component name\n *\n * @return Component observable\n */\nexport function useComponent(\n name: \"search-query\"\n): Observable\nexport function useComponent(\n name: Component\n): Observable\nexport function useComponent(\n name: Component\n): Observable {\n return components$\n .pipe(\n switchMap(components => (\n typeof components[name] !== \"undefined\"\n ? of(components[name] as T)\n : EMPTY\n )),\n distinctUntilChanged()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, combineLatest, pipe } from \"rxjs\"\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n zipWith\n} from \"rxjs/operators\"\n\nimport {\n Viewport,\n getElement,\n watchViewportAt\n} from \"browser\"\n\nimport { useComponent } from \"../../_\"\nimport {\n applyHeaderType,\n watchHeader\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header type\n */\nexport type HeaderType =\n | \"site\" /* Header shows site title */\n | \"page\" /* Header shows page title */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface Header {\n type: HeaderType /* Header type */\n sticky: boolean /* Header stickyness */\n height: number /* Header visible height */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount header from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountHeader(\n { document$, viewport$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const header$ = watchHeader(el, { document$ })\n\n /* Compute whether the header should switch to page header */\n const type$ = useComponent(\"main\")\n .pipe(\n map(main => getElement(\"h1, h2, h3, h4, h5, h6\", main)!),\n filter(hx => typeof hx !== \"undefined\"),\n zipWith(useComponent(\"header-title\")),\n switchMap(([hx, title]) => watchViewportAt(hx, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n return y >= hx.offsetHeight ? \"page\" : \"site\"\n }),\n distinctUntilChanged(),\n applyHeaderType(title)\n )\n ),\n startWith(\"site\")\n )\n\n /* Combine into single observable */\n return combineLatest([header$, type$])\n .pipe(\n map(([header, type]): Header => ({ type, ...header }))\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n of,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n shareReplay,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { watchElementSize } from \"browser\"\n\nimport { Header, HeaderType } from \"../_\"\nimport {\n resetHeaderTitleActive,\n setHeaderTitleActive\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header\n *\n * @param el - Header element\n *\n * @return Header observable\n */\nexport function watchHeader(\n el: HTMLElement, { document$ }: WatchOptions\n): Observable> {\n return document$\n .pipe(\n map(() => {\n const styles = getComputedStyle(el)\n return [\n \"sticky\", /* Modern browsers */\n \"-webkit-sticky\" /* Safari */\n ].includes(styles.position)\n }),\n distinctUntilChanged(),\n switchMap(sticky => {\n if (sticky) {\n return watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n sticky: true,\n height\n }))\n )\n } else {\n return of({\n sticky: false,\n height: 0\n })\n }\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply header title type\n *\n * @param el - Header title element\n *\n * @return Operator function\n */\nexport function applyHeaderType(\n el: HTMLElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(type => {\n setHeaderTitleActive(el, type === \"page\")\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetHeaderTitleActive(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header title active\n *\n * @param el - Header title element\n * @param value - Whether the title is shown\n */\nexport function setHeaderTitleActive(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"active\" : \"\")\n}\n\n/**\n * Reset header title active\n *\n * @param el - Header title element\n */\nexport function resetHeaderTitleActive(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n OperatorFunction,\n Subject,\n noop,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { useComponent } from \"../../_\"\nimport { Header } from \"../../header\"\nimport {\n applyHeaderShadow,\n watchMain\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Main area\n */\nexport interface Main {\n offset: number /* Main area top offset */\n height: number /* Main area visible height */\n active: boolean /* Scrolled past top offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount main area from source observable\n *\n * The header must be connected to the main area observable outside of the\n * operator function, as the header will persist in-between document switches\n * while the main area is replaced. However, the header observable must be\n * passed to this function, so we connect both via a long-living subject.\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountMain(\n { header$, viewport$ }: MountOptions\n): OperatorFunction {\n const main$ = new Subject
()\n\n /* Connect to main area observable via long-living subject */\n useComponent(\"header\")\n .pipe(\n switchMap(header => main$\n .pipe(\n distinctUntilKeyChanged(\"active\"),\n applyHeaderShadow(header)\n )\n )\n )\n .subscribe(noop)\n\n /* Return operator */\n return pipe(\n switchMap(el => watchMain(el, { header$, viewport$ })),\n tap(main => main$.next(main)),\n finalize(() => main$.complete())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchElementSize } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { Main } from \"../_\"\nimport {\n resetHeaderShadow,\n setHeaderShadow\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch main area\n *\n * This function returns an observable that computes the visual parameters of\n * the main area which depends on the viewport vertical offset and height, as\n * well as the height of the header element, if the header is fixed.\n *\n * @param el - Main area element\n * @param options - Options\n *\n * @return Main area observable\n */\nexport function watchMain(\n el: HTMLElement, { header$, viewport$ }: WatchOptions\n): Observable
{\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(({ height }) => height),\n distinctUntilChanged()\n )\n\n /* Compute the main area's top and bottom borders */\n const border$ = adjust$\n .pipe(\n switchMap(() => watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n top: el.offsetTop,\n bottom: el.offsetTop + height\n })),\n distinctUntilKeyChanged(\"bottom\")\n )\n )\n )\n\n /* Compute the main area's offset, visible height and if we scrolled past */\n return combineLatest([adjust$, border$, viewport$])\n .pipe(\n map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => {\n height = Math.max(0, height\n - Math.max(0, top - y, header)\n - Math.max(0, height + y - bottom)\n )\n return {\n offset: top - header,\n height,\n active: top - header <= y\n }\n }),\n distinctUntilChanged
((a, b) => {\n return a.offset === b.offset\n && a.height === b.height\n && a.active === b.active\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply header shadow\n *\n * @param el - Header element\n *\n * @return Operator function\n */\nexport function applyHeaderShadow(\n el: HTMLElement\n): MonoTypeOperatorFunction
{\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ active }) => {\n setHeaderShadow(el, active)\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetHeaderShadow(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header shadow\n *\n * @param el - Header element\n * @param value - Whether the shadow is shown\n */\nexport function setHeaderShadow(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"shadow\" : \"\")\n}\n\n/**\n * Reset header shadow\n *\n * @param el - Header element\n */\nexport function resetHeaderShadow(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar offset\n *\n * @param el - Sidebar element\n * @param value - Sidebar offset\n */\nexport function setSidebarOffset(\n el: HTMLElement, value: number\n): void {\n el.style.top = `${value}px`\n}\n\n/**\n * Reset sidebar offset\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarOffset(\n el: HTMLElement\n): void {\n el.style.top = \"\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar height\n *\n * This function doesn't set the height of the actual sidebar, but of its first\n * child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery\n * sidebars when the footer is scrolled into view. At some point we switched\n * from `absolute` / `fixed` positioning to `sticky` positioning, which greatly\n * reduced jitter in some browsers (respectively Firefox and Safari) when\n * scrolling from the top. However, top-aligned sticky positioning means that\n * the sidebar snaps to the bottom when the end of the container is reached.\n * This is what leads to the mentioned jitter, as the sidebar's height may be\n * updated to slowly.\n *\n * By setting the height of the sidebar to zero (while preserving `padding`),\n * and the height on its first element, this behaviour can be mitigiated. We\n * must assume that the top- and bottom offset (`padding`) are equal, as the\n * `offsetBottom` value is `undefined`.\n *\n * @param el - Sidebar element\n * @param value - Sidebar height\n */\nexport function setSidebarHeight(\n el: HTMLElement, value: number\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = `${value - 2 * scrollwrap.offsetTop}px`\n}\n\n/**\n * Reset sidebar height\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarHeight(\n el: HTMLElement\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { Header } from \"../../../header\"\nimport { Main } from \"../../../main\"\nimport { Sidebar } from \"../_\"\nimport {\n resetSidebarHeight,\n resetSidebarOffset,\n setSidebarHeight,\n setSidebarOffset\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n main$: Observable
/* Main area observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Apply options\n */\ninterface ApplyOptions {\n header$: Observable
/* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch sidebar\n *\n * This function returns an observable that computes the visual parameters of\n * the sidebar which depends on the vertical viewport offset, as well as the\n * height of the main area. When the page is scrolled beyond the header, the\n * sidebar is locked and fills the remaining space.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @return Sidebar observable\n */\nexport function watchSidebar(\n el: HTMLElement, { main$, viewport$ }: WatchOptions\n): Observable {\n const adjust = el.parentElement!.offsetTop\n - el.parentElement!.parentElement!.offsetTop\n\n /* Compute the sidebar's available height and if it should be locked */\n return combineLatest([main$, viewport$])\n .pipe(\n map(([{ offset, height }, { offset: { y } }]) => {\n height = height\n + Math.min(adjust, Math.max(0, y - offset))\n - adjust\n return {\n height,\n lock: y >= offset + adjust\n }\n }),\n distinctUntilChanged((a, b) => {\n return a.height === b.height\n && a.lock === b.lock\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply sidebar\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @return Operator function\n */\nexport function applySidebar(\n el: HTMLElement, { header$ }: ApplyOptions\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n withLatestFrom(header$),\n tap(([{ height, lock }, { height: offset }]) => {\n setSidebarHeight(el, height)\n\n /* Set offset in locked state depending on header height */\n if (lock)\n setSidebarOffset(el, offset)\n else\n resetSidebarOffset(el)\n }),\n\n /* Re-map to sidebar */\n map(([sidebar]) => sidebar),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSidebarOffset(el)\n resetSidebarHeight(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search transformation function\n *\n * @param value - Query value\n *\n * @return Transformed query value\n */\nexport type SearchTransformFn = (value: string) => string\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Default transformation function\n *\n * 1. Search for terms in quotation marks and prepend a `+` modifier to denote\n * that the resulting document must contain all terms, converting the query\n * to an `AND` query (as opposed to the default `OR` behavior). While users\n * may expect terms enclosed in quotation marks to map to span queries, i.e.\n * for which order is important, `lunr` doesn't support them, so the best\n * we can do is to convert the terms to an `AND` query.\n *\n * 2. Replace control characters which are not located at the beginning of the\n * query or preceded by white space, or are not followed by a non-whitespace\n * character or are at the end of the query string. Furthermore, filter\n * unmatched quotation marks.\n *\n * 3. Trim excess whitespace from left and right.\n *\n * @param query - Query value\n *\n * @return Transformed query value\n */\nexport function defaultTransform(query: string): string {\n return query\n .split(/\"([^\"]+)\"/g) /* => 1 */\n .map((terms, index) => index & 1\n ? terms.replace(/^\\b|^(?![^\\x00-\\x7F]|$)|\\s+/g, \" +\")\n : terms\n )\n .join(\"\")\n .replace(/\"|(?:^|\\s+)[*+\\-:^~]+(?=\\s+|$)/g, \"\") /* => 2 */\n .trim() /* => 3 */\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// tslint:disable no-null-keyword\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @return Element\n */\nexport function h(\n tag: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes))\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else if (attributes[attr])\n el.setAttribute(attr, \"\")\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElementOrThrow } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Translation keys\n */\ntype TranslateKey =\n | \"clipboard.copy\" /* Copy to clipboard */\n | \"clipboard.copied\" /* Copied to clipboard */\n | \"search.config.lang\" /* Search language */\n | \"search.config.pipeline\" /* Search pipeline */\n | \"search.config.separator\" /* Search separator */\n | \"search.placeholder\" /* Search */\n | \"search.result.placeholder\" /* Type to start searching */\n | \"search.result.none\" /* No matching documents */\n | \"search.result.one\" /* 1 matching document */\n | \"search.result.other\" /* # matching documents */\n | \"search.result.more.one\" /* 1 more on this page */\n | \"search.result.more.other\" /* # more on this page */\n | \"search.result.term.missing\" /* Missing */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Translations\n */\nlet lang: Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Translate the given key\n *\n * @param key - Key to be translated\n * @param value - Value to be replaced\n *\n * @return Translation\n */\nexport function translate(\n key: TranslateKey, value?: string | number\n): string {\n if (typeof lang === \"undefined\") {\n const el = getElementOrThrow(\"#__lang\")\n lang = JSON.parse(el.textContent!)\n }\n if (typeof lang[key] === \"undefined\") {\n throw new ReferenceError(`Invalid translation: ${key}`)\n }\n return typeof value !== \"undefined\"\n ? lang[key].replace(\"#\", value.toString())\n : lang[key]\n}\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @return Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0); // tslint:disable-line\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with source facts\n *\n * This is a reverse engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @return Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n\n/**\n * Simple hash function\n *\n * @see https://bit.ly/2wsVjJ4 - Original source\n *\n * @param value - Value to be hashed\n *\n * @return Hash as 32bit integer\n */\nexport function hash(value: string): number {\n let h = 0\n for (let i = 0, len = value.length; i < len; i++) {\n h = ((h << 5) - h) + value.charCodeAt(i)\n h |= 0 // Convert to 32bit integer\n }\n return h\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, asyncScheduler } from \"rxjs\"\nimport {\n map,\n observeOn,\n share,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, watchWorker } from \"browser\"\nimport { translate } from \"utilities\"\n\nimport { SearchIndex, SearchIndexPipeline } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchSetupMessage,\n isSearchResultMessage\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n index$: Observable /* Search index observable */\n base$: Observable /* Location base observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search index\n *\n * @param data - Search index\n *\n * @return Search index\n */\nfunction setupSearchIndex(\n { config, docs, index }: SearchIndex\n): SearchIndex {\n\n /* Override default language with value from translation */\n if (config.lang.length === 1 && config.lang[0] === \"en\")\n config.lang = [translate(\"search.config.lang\")]\n\n /* Override default separator with value from translation */\n if (config.separator === \"[\\\\s\\\\-]+\")\n config.separator = translate(\"search.config.separator\")\n\n /* Set pipeline from translation */\n const pipeline = translate(\"search.config.pipeline\")\n .split(/\\s*,\\s*/)\n .filter(Boolean) as SearchIndexPipeline\n\n /* Return search index after defaulting */\n return { config, docs, index, pipeline }\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search web worker\n *\n * This function will create a web worker to set up and query the search index\n * which is done using `lunr`. The index must be passed as an observable to\n * enable hacks like _localsearch_ via search index embedding as JSON.\n *\n * @param url - Worker URL\n * @param options - Options\n *\n * @return Worker handler\n */\nexport function setupSearchWorker(\n url: string, { index$, base$ }: SetupOptions\n): WorkerHandler {\n const worker = new Worker(url)\n\n /* Create communication channels and resolve relative links */\n const tx$ = new Subject()\n const rx$ = watchWorker(worker, { tx$ })\n .pipe(\n withLatestFrom(base$),\n map(([message, base]) => {\n if (isSearchResultMessage(message)) {\n for (const result of message.data)\n for (const document of result)\n document.location = `${base}/${document.location}`\n }\n return message\n }),\n share()\n )\n\n /* Set up search index */\n index$\n .pipe(\n map(data => ({\n type: SearchMessageType.SETUP,\n data: setupSearchIndex(data)\n })),\n observeOn(asyncScheduler)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Return worker handler */\n return { tx$, rx$ }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, fromEvent } from \"rxjs\"\nimport {\n map,\n share,\n switchMapTo,\n tap,\n throttle\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Worker message\n */\nexport interface WorkerMessage {\n type: unknown /* Message type */\n data?: unknown /* Message data */\n}\n\n/**\n * Worker handler\n *\n * @template T - Message type\n */\nexport interface WorkerHandler<\n T extends WorkerMessage\n> {\n tx$: Subject /* Message transmission subject */\n rx$: Observable /* Message receive observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n *\n * @template T - Worker message type\n */\ninterface WatchOptions {\n tx$: Observable /* Message transmission observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch a web worker\n *\n * This function returns an observable that will send all values emitted by the\n * message observable to the web worker. Web worker communication is expected\n * to be bidirectional (request-response) and synchronous. Messages that are\n * emitted during a pending request are throttled, the last one is emitted.\n *\n * @param worker - Web worker\n * @param options - Options\n *\n * @return Worker message observable\n */\nexport function watchWorker(\n worker: Worker, { tx$ }: WatchOptions\n): Observable {\n\n /* Intercept messages from worker-like objects */\n const rx$ = fromEvent(worker, \"message\")\n .pipe(\n map(({ data }) => data)\n )\n\n /* Send and receive messages, return hot observable */\n return tx$\n .pipe(\n throttle(() => rx$, { leading: true, trailing: true }),\n tap(message => worker.postMessage(message)),\n switchMapTo(rx$),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n SearchDocument,\n SearchMetadata,\n SearchResult\n} from \"integrations/search\"\nimport { h, translate, truncate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Render flag\n */\nconst enum Flag {\n TEASER = 1, /* Render teaser */\n PARENT = 2 /* Render as parent */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper function\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search document\n *\n * @param section - Search document\n * @param flag - Render flags\n *\n * @return Element\n */\nfunction renderSearchDocument(\n document: SearchDocument & SearchMetadata, flag: Flag\n) {\n const parent = flag & Flag.PARENT\n const teaser = flag & Flag.TEASER\n\n /* Render missing query terms */\n const missing = Object.keys(document.terms)\n .filter(key => !document.terms[key])\n .map(key => [{key}, \" \"])\n .flat()\n .slice(0, -1)\n\n /* Render article or section, depending on flags */\n const url = document.location\n return (\n \n \n {parent > 0 &&
}\n

{document.title}

\n {teaser > 0 && document.text.length > 0 &&\n

\n {truncate(document.text, 320)}\n

\n }\n {teaser > 0 && missing.length > 0 &&\n

\n {translate(\"search.result.term.missing\")}: {...missing}\n

\n }\n \n
\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n * @param threshold - Score threshold\n *\n * @return Element\n */\nexport function renderSearchResult(\n result: SearchResult, threshold: number = Infinity\n) {\n const docs = [...result]\n\n /* Find and extract parent article */\n const parent = docs.findIndex(doc => !doc.location.includes(\"#\"))\n const [article] = docs.splice(parent, 1)\n\n /* Determine last index above threshold */\n let index = docs.findIndex(doc => doc.score < threshold)\n if (index === -1)\n index = docs.length\n\n /* Partition sections */\n const best = docs.slice(0, index)\n const more = docs.slice(index)\n\n /* Render children */\n const children = [\n renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)),\n ...best.map(section => renderSearchDocument(section, Flag.TEASER)),\n ...more.length ? [\n
\n \n {more.length > 0 && more.length === 1\n ? translate(\"search.result.more.one\")\n : translate(\"search.result.more.other\", more.length)\n }\n \n {...more.map(section => renderSearchDocument(section, Flag.TEASER))}\n
\n ] : []\n ]\n\n /* Render search result */\n return (\n
  • \n {children}\n
  • \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SourceFacts } from \"patches/source\"\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render source facts\n *\n * @param facts - Source facts\n *\n * @return Element\n */\nexport function renderSource(\n facts: SourceFacts\n) {\n return (\n
      \n {facts.map(fact => (\n
    • {fact}
    • \n ))}\n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport * as ClipboardJS from \"clipboard\"\nimport { NEVER, Observable, Subject } from \"rxjs\"\nimport { mapTo, share, tap } from \"rxjs/operators\"\n\nimport { getElements } from \"browser\"\nimport { renderClipboardButton } from \"templates\"\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Observable /* Document observable */\n dialog$: Subject /* Dialog subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up clipboard\n *\n * This function implements the Clipboard.js integration and injects a button\n * into all code blocks when the document changes.\n *\n * @param options - Options\n *\n * @return Clipboard observable\n */\nexport function setupClipboard(\n { document$, dialog$ }: SetupOptions\n): Observable {\n if (!ClipboardJS.isSupported())\n return NEVER\n\n /* Inject 'copy-to-clipboard' buttons */\n document$.subscribe(() => {\n const blocks = getElements(\"pre > code\")\n blocks.forEach((block, index) => {\n const parent = block.parentElement!\n parent.id = `__code_${index}`\n parent.insertBefore(\n renderClipboardButton(parent.id),\n block\n )\n })\n })\n\n /* Initialize clipboard */\n const clipboard$ = new Observable(subscriber => {\n new ClipboardJS(\".md-clipboard\").on(\"success\", ev => subscriber.next(ev))\n })\n .pipe(\n share()\n )\n\n /* Display notification for clipboard event */\n clipboard$\n .pipe(\n tap(ev => ev.clearSelection()),\n mapTo(translate(\"clipboard.copied\"))\n )\n .subscribe(dialog$)\n\n /* Return clipboard */\n return clipboard$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h, translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @return Element\n */\nexport function renderClipboardButton(id: string) {\n return (\n code`}\n >\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, from, fromEvent, merge, of } from \"rxjs\"\nimport {\n bufferCount,\n catchError,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n sample,\n share,\n skip,\n switchMap\n} from \"rxjs/operators\"\n\nimport {\n Viewport,\n ViewportOffset,\n getElement,\n isAnchorLocation,\n isLocalLocation,\n replaceElement,\n setLocation,\n setLocationHash,\n setToggle,\n setViewportOffset\n} from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\ninterface State {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n location$: Subject /* Location subject */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up instant loading\n *\n * When fetching, theoretically, we could use `responseType: \"document\"`, but\n * since all MkDocs links are relative, we need to make sure that the current\n * location matches the document we just loaded. Otherwise any relative links\n * in the document could use the old location.\n *\n * This is the reason why we need to synchronize history events and the process\n * of fetching the document for navigation changes (except `popstate` events):\n *\n * 1. Fetch document via `XMLHTTPRequest`\n * 2. Set new location via `history.pushState`\n * 3. Parse and emit fetched document\n *\n * For `popstate` events, we must not use `history.pushState`, or the forward\n * history will be irreversibly overwritten. In case the request fails, the\n * location change is dispatched regularly.\n *\n * @param options - Options\n */\nexport function setupInstantLoading(\n urls: string[], { document$, viewport$, location$ }: SetupOptions\n): void {\n\n /* Disable automatic scroll restoration */\n if (\"scrollRestoration\" in history)\n history.scrollRestoration = \"manual\"\n\n /* Hack: ensure that reloads restore viewport offset */\n fromEvent(window, \"beforeunload\")\n .subscribe(() => {\n history.scrollRestoration = \"auto\"\n })\n\n /* Hack: ensure absolute favicon link to omit 404s on document switch */\n const favicon = getElement(`link[rel=\"shortcut icon\"]`)\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href // tslint:disable-line no-self-assignment\n\n /* Intercept link clicks and convert to state change */\n const state$ = fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n switchMap(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\")\n if (\n el && !el.target &&\n isLocalLocation(el) &&\n urls.includes(el.href)\n ) {\n if (!isAnchorLocation(el))\n ev.preventDefault()\n return of(el)\n }\n }\n return NEVER\n }),\n map(el => ({ url: new URL(el.href) })),\n share()\n )\n\n /* Always close search on link click */\n state$.subscribe(() => {\n setToggle(\"search\", false)\n })\n\n /* Filter state changes to dispatch */\n const push$ = state$\n .pipe(\n filter(({ url }) => !isAnchorLocation(url)),\n share()\n )\n\n /* Intercept popstate events (history back and forward) */\n const pop$ = fromEvent(window, \"popstate\")\n .pipe(\n filter(ev => ev.state !== null),\n map(ev => ({\n url: new URL(location.href),\n offset: ev.state\n })),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((prev, next) => prev.url.href === next.url.href),\n map(({ url }) => url)\n )\n .subscribe(location$)\n\n /* Fetch document on location change */\n const ajax$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n skip(1),\n switchMap(url => from(fetch(url.href, {\n credentials: \"same-origin\"\n }).then(res => res.text()))\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Set new location as soon as the document was fetched */\n push$\n .pipe(\n sample(ajax$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", url.toString())\n })\n\n /* Parse and emit document */\n const dom = new DOMParser()\n ajax$\n .pipe(\n map(response => dom.parseFromString(response, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Intercept instant loading */\n const instant$ = merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n\n // TODO: this must be combined with search scroll restoration on mobile\n instant$.subscribe(({ url, offset }) => {\n if (url.hash && !offset) {\n setLocationHash(url.hash)\n } else {\n setViewportOffset(offset || { y: 0 })\n }\n })\n\n /* Replace document metadata */\n document$\n .pipe(\n skip(1) // Skip initial\n )\n .subscribe(({ title, head }) => {\n document.title = title\n\n /* Replace meta tags */\n for (const selector of [\n `link[rel=\"canonical\"]`,\n `meta[name=\"author\"]`,\n `meta[name=\"description\"]`\n ]) {\n const next = getElement(selector, head)\n const prev = getElement(selector, document.head)\n if (\n typeof next !== \"undefined\" &&\n typeof prev !== \"undefined\"\n ) {\n replaceElement(prev, next)\n }\n }\n\n /* Finished, dispatch document switch event */\n document.dispatchEvent(new CustomEvent(\"DOMContentSwitch\"))\n })\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(state$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([prev, next]) => {\n return prev.url.pathname === next.url.pathname\n && !isAnchorLocation(next.url)\n }),\n map(([, state]) => state)\n )\n .subscribe(({ offset }) => {\n setViewportOffset(offset || { y: 0 })\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport {\n filter,\n map,\n share,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n Key,\n getActiveElement,\n getElement,\n getElements,\n getToggle,\n isSusceptibleToKeyboard,\n setElementFocus,\n setElementSelection,\n setToggle,\n watchKeyboard\n} from \"browser\"\nimport { useComponent } from \"components\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Keyboard mode\n */\nexport type KeyboardMode =\n | \"global\" /* Global */\n | \"search\" /* Search is open */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Keyboard\n */\nexport interface Keyboard extends Key {\n mode: KeyboardMode /* Keyboard mode */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up keyboard\n *\n * This function will set up the keyboard handlers and ensure that keys are\n * correctly propagated. Currently there are two modes:\n *\n * - `global`: This mode is active when the search is closed. It is intended\n * to assign hotkeys to specific functions of the site. Currently the search,\n * previous and next page can be triggered.\n *\n * - `search`: This mode is active when the search is open. It maps certain\n * navigational keys to offer search results that can be entirely navigated\n * through keyboard input.\n *\n * The keyboard observable is returned and can be used to monitor the keyboard\n * in order toassign further hotkeys to custom functions.\n *\n * @return Keyboard observable\n */\nexport function setupKeyboard(): Observable {\n const keyboard$ = watchKeyboard()\n .pipe(\n map(key => ({\n mode: getToggle(\"search\") ? \"search\" : \"global\",\n ...key\n })),\n filter(({ mode }) => {\n if (mode === \"global\") {\n const active = getActiveElement()\n if (typeof active !== \"undefined\")\n return !isSusceptibleToKeyboard(active)\n }\n return true\n }),\n share()\n )\n\n /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\"),\n withLatestFrom(\n useComponent(\"search-query\"),\n useComponent(\"search-result\")\n )\n )\n .subscribe(([key, query, result]) => {\n const active = getActiveElement()\n switch (key.type) {\n\n /* Enter: prevent form submission */\n case \"Enter\":\n if (active === query)\n key.claim()\n break\n\n /* Escape or Tab: close search */\n case \"Escape\":\n case \"Tab\":\n setToggle(\"search\", false)\n setElementFocus(query, false)\n break\n\n /* Vertical arrows: select previous or next search result */\n case \"ArrowUp\":\n case \"ArrowDown\":\n if (typeof active === \"undefined\") {\n setElementFocus(query)\n } else {\n const els = [query, ...getElements(\n \":not(details) > [href], summary, details[open] [href]\",\n result\n )]\n const i = Math.max(0, (\n Math.max(0, els.indexOf(active)) + els.length + (\n key.type === \"ArrowUp\" ? -1 : +1\n )\n ) % els.length)\n setElementFocus(els[i])\n }\n\n /* Prevent scrolling of page */\n key.claim()\n break\n\n /* All other keys: hand to search query */\n default:\n if (query !== getActiveElement())\n setElementFocus(query)\n }\n })\n\n /* Set up global keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\"),\n withLatestFrom(useComponent(\"search-query\"))\n )\n .subscribe(([key, query]) => {\n switch (key.type) {\n\n /* Open search and select query */\n case \"f\":\n case \"s\":\n case \"/\":\n setElementFocus(query)\n setElementSelection(query)\n key.claim()\n break\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getElement(\"[href][rel=prev]\")\n if (typeof prev !== \"undefined\")\n prev.click()\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getElement(\"[href][rel=next]\")\n if (typeof next !== \"undefined\")\n next.click()\n break\n }\n })\n\n /* Return keyboard */\n return keyboard$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { filter, map, share } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Key\n */\nexport interface Key {\n type: string /* Key type */\n claim(): void /* Key claim */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether an element may receive keyboard input\n *\n * @param el - Element\n *\n * @return Test result\n */\nexport function isSusceptibleToKeyboard(el: HTMLElement): boolean {\n switch (el.tagName) {\n\n /* Form elements */\n case \"INPUT\":\n case \"SELECT\":\n case \"TEXTAREA\":\n return true\n\n /* Everything else */\n default:\n return el.isContentEditable\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch keyboard\n *\n * @return Keyboard observable\n */\nexport function watchKeyboard(): Observable {\n return fromEvent(window, \"keydown\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n map(ev => ({\n type: ev.key,\n claim() {\n ev.preventDefault()\n ev.stopPropagation()\n }\n })),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element text selection\n *\n * @param el - Element\n */\nexport function setElementSelection(\n el: HTMLElement\n): void {\n if (el instanceof HTMLInputElement)\n el.select()\n else\n throw new Error(\"Not implemented\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set search query placeholder\n *\n * @param el - Search query element\n * @param value - Placeholder\n */\nexport function setSearchQueryPlaceholder(\n el: HTMLInputElement, value: string\n): void {\n el.placeholder = value\n}\n\n/**\n * Reset search query placeholder\n *\n * @param el - Search query element\n */\nexport function resetSearchQueryPlaceholder(\n el: HTMLInputElement\n): void {\n el.placeholder = translate(\"search.placeholder\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n combineLatest,\n fromEvent,\n merge,\n pipe\n} from \"rxjs\"\nimport {\n delay,\n distinctUntilChanged,\n finalize,\n map,\n startWith,\n tap\n} from \"rxjs/operators\"\n\nimport { watchElementFocus } from \"browser\"\nimport { SearchTransformFn, defaultTransform } from \"integrations\"\n\nimport { SearchQuery } from \"../_\"\nimport {\n resetSearchQueryPlaceholder,\n setSearchQueryPlaceholder\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n transform?: SearchTransformFn /* Transformation function */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search query\n *\n * Note that the focus event which triggers re-reading the current query value\n * is delayed by `1ms` so the input's empty state is allowed to propagate.\n *\n * @param el - Search query element\n * @param options - Options\n *\n * @return Search query observable\n */\nexport function watchSearchQuery(\n el: HTMLInputElement, { transform }: WatchOptions = {}\n): Observable {\n const fn = transform || defaultTransform\n\n /* Intercept keyboard events */\n const value$ = merge(\n fromEvent(el, \"keyup\"),\n fromEvent(el, \"focus\").pipe(delay(1))\n )\n .pipe(\n map(() => fn(el.value)),\n startWith(fn(el.value)),\n distinctUntilChanged()\n )\n\n /* Intercept focus events */\n const focus$ = watchElementFocus(el)\n\n /* Combine into single observable */\n return combineLatest([value$, focus$])\n .pipe(\n map(([value, focus]) => ({ value, focus }))\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply search query\n *\n * @param el - Search query element\n *\n * @return Operator function\n */\nexport function applySearchQuery(\n el: HTMLInputElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Hide placeholder when search is focused */\n tap(({ focus }) => {\n if (focus) {\n setSearchQueryPlaceholder(el, \"\")\n } else {\n resetSearchQueryPlaceholder(el)\n }\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSearchQueryPlaceholder(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { OperatorFunction, pipe } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, setToggle } from \"browser\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchQueryMessage,\n SearchTransformFn\n} from \"integrations\"\n\nimport {\n applySearchQuery,\n watchSearchQuery\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query\n */\nexport interface SearchQuery {\n value: string /* Query value */\n focus: boolean /* Query focus */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n transform?: SearchTransformFn /* Transformation function */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search query from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearchQuery(\n { tx$ }: WorkerHandler, options: MountOptions = {}\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const query$ = watchSearchQuery(el, options)\n\n /* Subscribe worker to search query */\n query$\n .pipe(\n distinctUntilKeyChanged(\"value\"),\n map(({ value }): SearchQueryMessage => ({\n type: SearchMessageType.QUERY,\n data: value\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Toggle search on focus */\n query$\n .pipe(\n distinctUntilKeyChanged(\"focus\")\n )\n .subscribe(({ focus }) => {\n if (focus)\n setToggle(\"search\", focus)\n })\n\n /* Return search query */\n return query$\n .pipe(\n applySearchQuery(el)\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { OperatorFunction, pipe } from \"rxjs\"\nimport {\n mapTo,\n startWith,\n switchMap,\n switchMapTo,\n tap\n} from \"rxjs/operators\"\n\nimport { setElementFocus } from \"browser\"\n\nimport { useComponent } from \"../../../_\"\nimport { watchSearchReset } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search reset from source observable\n *\n * @return Operator function\n */\nexport function mountSearchReset(): OperatorFunction {\n return pipe(\n switchMap(el => watchSearchReset(el)\n .pipe(\n switchMapTo(useComponent(\"search-query\")),\n tap(setElementFocus),\n mapTo(undefined)\n )\n ),\n startWith(undefined)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search reset\n *\n * @param el - Search reset element\n *\n * @return Search reset observable\n */\nexport function watchSearchReset(\n el: HTMLElement\n): Observable {\n return fromEvent(el, \"click\")\n .pipe(\n mapTo(undefined)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set number of search results\n *\n * @param el - Search result metadata element\n * @param value - Number of results\n */\nexport function setSearchResultMeta(\n el: HTMLElement, value: number\n): void {\n switch (value) {\n\n /* No results */\n case 0:\n el.textContent = translate(\"search.result.none\")\n break\n\n /* One result */\n case 1:\n el.textContent = translate(\"search.result.one\")\n break\n\n /* Multiple result */\n default:\n el.textContent = translate(\"search.result.other\", value)\n }\n}\n\n/**\n * Reset number of search results\n *\n * @param el - Search result metadata element\n */\nexport function resetSearchResultMeta(\n el: HTMLElement\n): void {\n el.textContent = translate(\"search.result.placeholder\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Add an element to the search result list\n *\n * @param el - Search result list element\n * @param child - Search result element\n */\nexport function addToSearchResultList(\n el: HTMLElement, child: Element\n): void {\n el.appendChild(child)\n}\n\n/**\n * Reset search result list\n *\n * @param el - Search result list element\n */\nexport function resetSearchResultList(\n el: HTMLElement\n): void {\n el.innerHTML = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n pipe\n} from \"rxjs\"\nimport {\n finalize,\n map,\n mapTo,\n observeOn,\n scan,\n switchMap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"browser\"\nimport { SearchResult } from \"integrations/search\"\nimport { renderSearchResult } from \"templates\"\n\nimport { SearchQuery } from \"../../query\"\nimport {\n addToSearchResultList,\n resetSearchResultList,\n resetSearchResultMeta,\n setSearchResultMeta\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply options\n */\ninterface ApplyOptions {\n query$: Observable /* Search query observable */\n ready$: Observable /* Search ready observable */\n fetch$: Observable /* Result fetch observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply search results\n *\n * This function will perform a lazy rendering of the search results, depending\n * on the vertical offset of the search result container. When the scroll offset\n * reaches the bottom of the element, more results are fetched and rendered.\n *\n * @param el - Search result element\n * @param options - Options\n *\n * @return Operator function\n */\nexport function applySearchResult(\n el: HTMLElement, { query$, ready$, fetch$ }: ApplyOptions\n): MonoTypeOperatorFunction {\n const list = getElementOrThrow(\".md-search-result__list\", el)\n const meta = getElementOrThrow(\".md-search-result__meta\", el)\n return pipe(\n\n /* Apply search result metadata */\n withLatestFrom(query$, ready$),\n map(([result, query]) => {\n if (query.value) {\n setSearchResultMeta(meta, result.length)\n } else {\n resetSearchResultMeta(meta)\n }\n return result\n }),\n\n /* Apply search result list */\n switchMap(result => {\n const thresholds = [...result.map(([best]) => best.score), 0]\n return fetch$\n .pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n scan(index => {\n const container = el.parentElement!\n while (index < result.length) {\n addToSearchResultList(list, renderSearchResult(\n result[index++], thresholds[index]\n ))\n if (container.scrollHeight - container.offsetHeight > 16)\n break\n }\n return index\n }, 0),\n\n /* Re-map to search result */\n mapTo(result),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSearchResultList(list)\n })\n )\n }\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, pipe } from \"rxjs\"\nimport {\n distinctUntilChanged,\n filter,\n map,\n mapTo,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, watchElementOffset } from \"browser\"\nimport {\n SearchMessage,\n SearchResult,\n isSearchReadyMessage,\n isSearchResultMessage\n} from \"integrations\"\n\nimport { SearchQuery } from \"../../query\"\nimport { applySearchResult } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search result from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearchResult(\n { rx$ }: WorkerHandler, { query$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const container = el.parentElement!\n\n /* Compute if search is ready */\n const ready$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n mapTo(true)\n )\n\n /* Compute whether there are more search results to fetch */\n const fetch$ = watchElementOffset(container)\n .pipe(\n map(({ y }) => {\n return y >= container.scrollHeight - container.offsetHeight - 16\n }),\n distinctUntilChanged(),\n filter(Boolean)\n )\n\n /* Apply search results */\n return rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => data),\n applySearchResult(el, { query$, ready$, fetch$ }),\n startWith([])\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, of, pipe } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchViewportAt } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { applyTabs } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Tabs\n */\nexport interface Tabs {\n hidden: boolean /* Whether the tabs are hidden */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n viewport$: Observable /* Viewport observable */\n screen$: Observable /* Media screen observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount tabs from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountTabs(\n { header$, viewport$, screen$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => screen$\n .pipe(\n switchMap(screen => {\n\n /* [screen +]: Mount tabs above screen breakpoint */\n if (screen) {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => ({ hidden: y >= 10 })),\n distinctUntilKeyChanged(\"hidden\"),\n applyTabs(el)\n )\n\n /* [screen -]: Unmount tabs below screen breakpoint */\n } else {\n return of({ hidden: true })\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n animationFrameScheduler,\n pipe\n} from \"rxjs\"\nimport { finalize, observeOn, tap } from \"rxjs/operators\"\n\nimport { Tabs } from \"../_\"\nimport {\n resetTabsHidden,\n setTabsHidden\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply tabs\n *\n * @param el - Tabs element\n *\n * @return Operator function\n */\nexport function applyTabs(\n el: HTMLElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ hidden }) => {\n setTabsHidden(el, hidden)\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetTabsHidden(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set tabs hidden\n *\n * @param el - Tabs element\n * @param value - Whether the element is hidden\n */\nexport function setTabsHidden(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"hidden\" : \"\")\n}\n\n/**\n * Reset tabs hidden\n *\n * @param el - Tabs element\n */\nexport function resetTabsHidden(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set anchor blur\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is blurred\n */\nexport function setAnchorBlur(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"blur\" : \"\")\n}\n\n/**\n * Reset anchor blur\n *\n * @param el - Anchor element\n */\nexport function resetAnchorBlur(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set anchor active\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is active\n */\nexport function setAnchorActive(\n el: HTMLElement, value: boolean\n): void {\n el.classList.toggle(\"md-nav__link--active\", value)\n}\n\n/**\n * Reset anchor active\n *\n * @param el - Anchor element\n */\nexport function resetAnchorActive(\n el: HTMLElement\n): void {\n el.classList.remove(\"md-nav__link--active\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n OperatorFunction,\n combineLatest,\n of,\n pipe\n} from \"rxjs\"\nimport { map, switchMap } from \"rxjs/operators\"\n\nimport { Viewport, getElements } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { Main } from \"../../main\"\nimport {\n Sidebar,\n applySidebar,\n watchSidebar\n} from \"../../shared\"\nimport {\n AnchorList,\n applyAnchorList,\n watchAnchorList\n} from \"../anchor\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Table of contents for [tablet -]\n */\ninterface TableOfContentsBelowTablet {} // tslint:disable-line\n\n/**\n * Table of contents for [tablet +]\n */\ninterface TableOfContentsAboveTablet {\n sidebar: Sidebar /* Sidebar */\n anchors: AnchorList /* Anchor list */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Table of contents\n */\nexport type TableOfContents =\n | TableOfContentsBelowTablet\n | TableOfContentsAboveTablet\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n viewport$: Observable /* Viewport observable */\n tablet$: Observable /* Tablet media observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount table of contents from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountTableOfContents(\n { header$, main$, viewport$, tablet$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => tablet$\n .pipe(\n switchMap(tablet => {\n\n /* [tablet +]: Mount table of contents in sidebar */\n if (tablet) {\n const els = getElements(\".md-nav__link\", el)\n\n /* Watch and apply sidebar */\n const sidebar$ = watchSidebar(el, { main$, viewport$ })\n .pipe(\n applySidebar(el, { header$ })\n )\n\n /* Watch and apply anchor list (scroll spy) */\n const anchors$ = watchAnchorList(els, { header$, viewport$ })\n .pipe(\n applyAnchorList(els)\n )\n\n /* Combine into single hot observable */\n return combineLatest([sidebar$, anchors$])\n .pipe(\n map(([sidebar, anchors]) => ({ sidebar, anchors }))\n )\n\n /* [tablet -]: Unmount table of contents */\n } else {\n return of({})\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n bufferCount,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n scan,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport, getElement, watchElementSize } from \"browser\"\n\nimport { Header } from \"../../../header\"\nimport { AnchorList } from \"../_\"\nimport {\n resetAnchorActive,\n resetAnchorBlur,\n setAnchorActive,\n setAnchorBlur\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n header$: Observable
    /* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch anchor list\n *\n * This is effectively a scroll-spy implementation which will account for the\n * fixed header and automatically re-calculate anchor offsets when the viewport\n * is resized. The returned observable will only emit if the anchor list needs\n * to be repainted.\n *\n * This implementation tracks an anchor element's entire path starting from its\n * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the\n * Material theme currently doesn't make use of this information, it enables\n * the styling of the entire hierarchy through customization.\n *\n * Note that the current anchor is the last item of the `prev` anchor list.\n *\n * @param els - Anchor elements\n * @param options - Options\n *\n * @return Anchor list observable\n */\nexport function watchAnchorList(\n els: HTMLAnchorElement[], { header$, viewport$ }: WatchOptions\n): Observable {\n const table = new Map()\n for (const el of els) {\n const id = decodeURIComponent(el.hash.substring(1))\n const target = getElement(`[id=\"${id}\"]`)\n if (typeof target !== \"undefined\")\n table.set(el, target)\n }\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(header => 18 + header.height)\n )\n\n /* Compute partition of previous and next anchors */\n const partition$ = watchElementSize(document.body)\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n\n /* Build index to map anchor paths to vertical offsets */\n map(() => {\n let path: HTMLAnchorElement[] = []\n return [...table].reduce((index, [anchor, target]) => {\n while (path.length) {\n const last = table.get(path[path.length - 1])!\n if (last.tagName >= target.tagName) {\n path.pop()\n } else {\n break\n }\n }\n\n /* If the current anchor is hidden, continue with its parent */\n let offset = target.offsetTop\n while (!offset && target.parentElement) {\n target = target.parentElement\n offset = target.offsetTop\n }\n\n /* Map reversed anchor path to vertical offset */\n return index.set(\n [...path = [...path, anchor]].reverse(),\n offset\n )\n }, new Map())\n }),\n\n /* Re-compute partition when viewport offset changes */\n switchMap(index => combineLatest([adjust$, viewport$])\n .pipe(\n scan(([prev, next], [adjust, { offset: { y } }]) => {\n\n /* Look forward */\n while (next.length) {\n const [, offset] = next[0]\n if (offset - adjust < y) {\n prev = [...prev, next.shift()!]\n } else {\n break\n }\n }\n\n /* Look backward */\n while (prev.length) {\n const [, offset] = prev[prev.length - 1]\n if (offset - adjust >= y) {\n next = [prev.pop()!, ...next]\n } else {\n break\n }\n }\n\n /* Return partition */\n return [prev, next]\n }, [[], [...index]]),\n distinctUntilChanged((a, b) => {\n return a[0] === b[0]\n && a[1] === b[1]\n })\n )\n )\n )\n\n /* Compute and return anchor list migrations */\n return partition$\n .pipe(\n map(([prev, next]) => ({\n prev: prev.map(([path]) => path),\n next: next.map(([path]) => path)\n })),\n\n /* Extract anchor list migrations */\n startWith({ prev: [], next: [] }),\n bufferCount(2, 1),\n map(([a, b]) => {\n\n /* Moving down */\n if (a.prev.length < b.prev.length) {\n return {\n prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length),\n next: []\n }\n\n /* Moving up */\n } else {\n return {\n prev: b.prev.slice(-1),\n next: b.next.slice(0, b.next.length - a.next.length)\n }\n }\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply anchor list\n *\n * @param els - Anchor elements\n *\n * @return Operator function\n */\nexport function applyAnchorList(\n els: HTMLAnchorElement[]\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ prev, next }) => {\n\n /* Look forward */\n for (const [el] of next) {\n resetAnchorActive(el)\n resetAnchorBlur(el)\n }\n\n /* Look backward */\n prev.forEach(([el], index) => {\n setAnchorActive(el, index === prev.length - 1)\n setAnchorBlur(el, true)\n })\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n for (const el of els) {\n resetAnchorActive(el)\n resetAnchorBlur(el)\n }\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, fromEvent, iif, merge } from \"rxjs\"\nimport { map, mapTo, shareReplay, switchMap } from \"rxjs/operators\"\n\nimport { getElements } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether the given device is an Apple device\n *\n * @return Test result\n */\nfunction isAppleDevice(): boolean {\n return /(iPad|iPhone|iPod)/.test(navigator.userAgent)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all elements with `data-md-scrollfix` attributes\n *\n * This is a year-old patch which ensures that overflow scrolling works at the\n * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon\n * the start of a touch event.\n *\n * @see https://bit.ly/2SCtAOO - Original source\n *\n * @param options - Options\n */\nexport function patchScrollfix(\n { document$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"[data-md-scrollfix]\")),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Remove marker attribute, so we'll only add the fix once */\n els$.subscribe(els => {\n for (const el of els)\n el.removeAttribute(\"data-md-scrollfix\")\n })\n\n /* Patch overflow scrolling on touch start */\n iif(isAppleDevice, els$, NEVER)\n .pipe(\n switchMap(els => merge(...els.map(el => (\n fromEvent(el, \"touchstart\")\n .pipe(\n mapTo(el)\n )\n ))))\n )\n .subscribe(el => {\n const top = el.scrollTop\n\n /* We're at the top of the container */\n if (top === 0) {\n el.scrollTop = 1\n\n /* We're at the bottom of the container */\n } else if (top + el.offsetHeight === el.scrollHeight) {\n el.scrollTop = top - 1\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable } from \"rxjs\"\nimport { catchError, filter, map, switchMap } from \"rxjs/operators\"\n\nimport { getElementOrThrow, getElements } from \"browser\"\nimport { renderSource } from \"templates\"\nimport { cache, hash } from \"utilities\"\n\nimport { fetchSourceFactsFromGitHub } from \"./github\"\nimport { fetchSourceFactsFromGitLab } from \"./gitlab\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Source facts\n */\nexport type SourceFacts = string[]\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch source facts\n *\n * @param url - Source repository URL\n *\n * @return Source facts observable\n */\nfunction fetchSourceFacts(\n url: string\n): Observable {\n const [type] = url.match(/(git(?:hub|lab))/i) || []\n switch (type.toLowerCase()) {\n\n /* GitHub repository */\n case \"github\":\n const [, user, repo] = url.match(/^.+github\\.com\\/([^\\/]+)\\/?([^\\/]+)?/i)!\n return fetchSourceFactsFromGitHub(user, repo)\n\n /* GitLab repository */\n case \"gitlab\":\n const [, base, slug] = url.match(/^.+?([^\\/]*gitlab[^\\/]+)\\/(.+?)\\/?$/i)!\n return fetchSourceFactsFromGitLab(base, slug)\n\n /* Everything else */\n default:\n return NEVER\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch elements containing repository information\n *\n * This function will retrieve the URL from the repository link and try to\n * query data from integrated source code platforms like GitHub or GitLab.\n *\n * @param options - Options\n */\nexport function patchSource(\n { document$ }: PatchOptions\n): void {\n document$\n .pipe(\n map(() => getElementOrThrow(\".md-source[href]\")),\n switchMap(({ href }) => (\n cache(`${hash(href)}`, () => fetchSourceFacts(href))\n )),\n filter(facts => facts.length > 0),\n catchError(() => NEVER)\n )\n .subscribe(facts => {\n for (const el of getElements(\".md-source__repository\")) {\n if (!el.hasAttribute(\"data-md-state\")) {\n el.setAttribute(\"data-md-state\", \"done\")\n el.appendChild(renderSource(facts))\n }\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Repo, User } from \"github-types\"\nimport { Observable, from } from \"rxjs\"\nimport {\n defaultIfEmpty,\n filter,\n map,\n share,\n switchMap\n} from \"rxjs/operators\"\n\nimport { round } from \"utilities\"\n\nimport { SourceFacts } from \"..\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitHub source facts\n *\n * @param user - GitHub user\n * @param repo - GitHub repository\n *\n * @return Source facts observable\n */\nexport function fetchSourceFactsFromGitHub(\n user: string, repo?: string\n): Observable {\n const url = typeof repo !== \"undefined\"\n ? `https://api.github.com/repos/${user}/${repo}`\n : `https://api.github.com/users/${user}`\n return from(fetch(url))\n .pipe(\n filter(res => res.status === 200),\n switchMap(res => res.json()),\n map(data => {\n\n /* GitHub repository */\n if (typeof repo !== \"undefined\") {\n const { stargazers_count, forks_count }: Repo = data\n return [\n `${round(stargazers_count!)} Stars`,\n `${round(forks_count!)} Forks`\n ]\n\n /* GitHub user/organization */\n } else {\n const { public_repos }: User = data\n return [\n `${round(public_repos!)} Repositories`\n ]\n }\n }),\n defaultIfEmpty([]),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ProjectSchema } from \"gitlab\"\nimport { Observable, from } from \"rxjs\"\nimport {\n defaultIfEmpty,\n filter,\n map,\n share,\n switchMap\n} from \"rxjs/operators\"\n\nimport { round } from \"utilities\"\n\nimport { SourceFacts } from \"..\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitLab source facts\n *\n * @param base - GitLab base\n * @param project - GitLab project\n *\n * @return Source facts observable\n */\nexport function fetchSourceFactsFromGitLab(\n base: string, project: string\n): Observable {\n const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`\n return from(fetch(url))\n .pipe(\n filter(res => res.status === 200),\n switchMap(res => res.json()),\n map(({ star_count, forks_count }: ProjectSchema) => ([\n `${round(star_count)} Stars`,\n `${round(forks_count)} Forks`\n ])),\n defaultIfEmpty([]),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, defer, of } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Cache the last value emitted by an observable in session storage\n *\n * If the key is not found in session storage, the factory is executed and the\n * latest value emitted will automatically be persisted to sessions storage.\n * Note that the values emitted by the returned observable must be serializable\n * as `JSON`, or data will be lost.\n *\n * @template T - Value type\n *\n * @param key - Cache key\n * @param factory - Observable factory\n *\n * @return Value observable\n */\nexport function cache(\n key: string, factory: () => Observable\n): Observable {\n return defer(() => {\n const data = sessionStorage.getItem(key)\n if (data) {\n return of(JSON.parse(data) as T)\n\n /* Retrieve value from observable factory and write to storage */\n } else {\n const value$ = factory()\n value$.subscribe(value => {\n try {\n sessionStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n /* Uncritical, just swallow */\n }\n })\n\n /* Return value */\n return value$\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// DISCLAIMER: this file is still WIP. There're some refactoring opportunities\n// which must be tackled after we gathered some feedback on v5.\n// tslint:disable\n\nimport \"focus-visible\"\n\nimport {\n merge,\n combineLatest,\n animationFrameScheduler,\n fromEvent,\n from,\n defer,\n of,\n NEVER\n} from \"rxjs\"\nimport {\n delay,\n switchMap,\n tap,\n filter,\n withLatestFrom,\n observeOn,\n take,\n shareReplay,\n catchError,\n map,\n bufferCount,\n distinctUntilKeyChanged\n} from \"rxjs/operators\"\n\nimport {\n watchToggle,\n setToggle,\n getElements,\n watchMedia,\n watchDocument,\n watchLocation,\n watchLocationHash,\n watchViewport,\n isLocalLocation,\n setLocationHash,\n watchLocationBase,\n getElement\n} from \"browser\"\nimport {\n mountHeader,\n mountMain,\n mountNavigation,\n mountSearch,\n mountTableOfContents,\n mountTabs,\n useComponent,\n setupComponents,\n mountSearchQuery,\n mountSearchReset,\n mountSearchResult\n} from \"components\"\nimport {\n setupClipboard,\n setupDialog,\n setupKeyboard,\n setupInstantLoading,\n setupSearchWorker,\n SearchIndex,\n SearchIndexPipeline\n} from \"integrations\"\nimport {\n patchCodeBlocks,\n patchTables,\n patchDetails,\n patchScrollfix,\n patchSource,\n patchScripts\n} from \"patches\"\nimport { isConfig } from \"utilities\"\n\n/* ------------------------------------------------------------------------- */\n\n/* Denote that JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Test for iOS */\nif (navigator.userAgent.match(/(iPad|iPhone|iPod)/g))\n document.documentElement.classList.add(\"ios\")\n\n/**\n * Set scroll lock\n *\n * @param el - Scrollable element\n * @param value - Vertical offset\n */\nexport function setScrollLock(\n el: HTMLElement, value: number\n): void {\n el.setAttribute(\"data-md-state\", \"lock\")\n el.style.top = `-${value}px`\n}\n\n/**\n * Reset scroll lock\n *\n * @param el - Scrollable element\n */\nexport function resetScrollLock(\n el: HTMLElement\n): void {\n const value = -1 * parseInt(el.style.top, 10)\n el.removeAttribute(\"data-md-state\")\n el.style.top = \"\"\n if (value)\n window.scrollTo(0, value)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Initialize Material for MkDocs\n *\n * @param config - Configuration\n */\nexport function initialize(config: unknown) {\n if (!isConfig(config))\n throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)\n\n /* Set up subjects */\n const document$ = watchDocument()\n const location$ = watchLocation()\n\n /* Set up user interface observables */\n const base$ = watchLocationBase(config.base, { location$ })\n const hash$ = watchLocationHash()\n const viewport$ = watchViewport()\n const tablet$ = watchMedia(\"(min-width: 960px)\")\n const screen$ = watchMedia(\"(min-width: 1220px)\")\n\n /* ----------------------------------------------------------------------- */\n\n /* Set up component bindings */\n setupComponents([\n \"announce\", /* Announcement bar */\n \"container\", /* Container */\n \"header\", /* Header */\n \"header-title\", /* Header title */\n \"main\", /* Main area */\n \"navigation\", /* Navigation */\n \"search\", /* Search */\n \"search-query\", /* Search input */\n \"search-reset\", /* Search reset */\n \"search-result\", /* Search results */\n \"skip\", /* Skip link */\n \"tabs\", /* Tabs */\n \"toc\" /* Table of contents */\n ], { document$ })\n\n const keyboard$ = setupKeyboard()\n\n // Hack: only make code blocks focusable on non-touch devices\n if (matchMedia(\"(hover)\").matches)\n patchCodeBlocks({ document$, viewport$ })\n patchDetails({ document$, hash$ })\n patchScripts({ document$ })\n patchSource({ document$ })\n patchTables({ document$ })\n\n /* Force 1px scroll offset to trigger overflow scrolling */\n patchScrollfix({ document$ })\n\n /* Set up clipboard and dialog */\n const dialog$ = setupDialog()\n const clipboard$ = setupClipboard({ document$, dialog$ })\n\n /* ----------------------------------------------------------------------- */\n\n /* Create header observable */\n const header$ = useComponent(\"header\")\n .pipe(\n mountHeader({ document$, viewport$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n const main$ = useComponent(\"main\")\n .pipe(\n mountMain({ header$, viewport$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n const navigation$ = useComponent(\"navigation\")\n .pipe(\n mountNavigation({ header$, main$, viewport$, screen$ }),\n shareReplay({ bufferSize: 1, refCount: true }) // shareReplay because there might be late subscribers\n )\n\n const toc$ = useComponent(\"toc\")\n .pipe(\n mountTableOfContents({ header$, main$, viewport$, tablet$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n const tabs$ = useComponent(\"tabs\")\n .pipe(\n mountTabs({ header$, viewport$, screen$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n /* Search worker - only if search is present */\n const worker$ = useComponent(\"search\")\n .pipe(\n switchMap(() => defer(() => {\n const index = config.search && config.search.index\n ? config.search.index\n : undefined\n\n /* Fetch index if it wasn't passed explicitly */\n const index$ = (\n typeof index !== \"undefined\"\n ? from(index)\n : base$\n .pipe(\n switchMap(base => fetch(`${base}/search/search_index.json`, {\n credentials: \"same-origin\"\n }).then(res => res.json())) // SearchIndex\n )\n )\n\n return of(setupSearchWorker(config.search.worker, {\n base$, index$\n }))\n }))\n )\n\n /* ----------------------------------------------------------------------- */\n\n /* Mount search query */\n const search$ = worker$\n .pipe(\n switchMap(worker => {\n\n const query$ = useComponent(\"search-query\")\n .pipe(\n mountSearchQuery(worker, { transform: config.search.transform }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Mount search reset */\n const reset$ = useComponent(\"search-reset\")\n .pipe(\n mountSearchReset(),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Mount search result */\n const result$ = useComponent(\"search-result\")\n .pipe(\n mountSearchResult(worker, { query$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n return useComponent(\"search\")\n .pipe(\n mountSearch(worker, { query$, reset$, result$ }),\n )\n }),\n catchError(() => {\n useComponent(\"search\")\n .subscribe(el => el.hidden = true) // TODO: Hack\n return NEVER\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n // // put into search...\n hash$\n .pipe(\n tap(() => setToggle(\"search\", false)),\n delay(125), // ensure that it runs after the body scroll reset...\n )\n .subscribe(hash => setLocationHash(`#${hash}`))\n\n // TODO: scroll restoration must be centralized\n combineLatest([\n watchToggle(\"search\"),\n tablet$,\n ])\n .pipe(\n withLatestFrom(viewport$),\n switchMap(([[toggle, tablet], { offset: { y }}]) => {\n const active = toggle && !tablet\n return document$\n .pipe(\n delay(active ? 400 : 100),\n observeOn(animationFrameScheduler),\n tap(({ body }) => active\n ? setScrollLock(body, y)\n : resetScrollLock(body)\n )\n )\n })\n )\n .subscribe()\n\n /* ----------------------------------------------------------------------- */\n\n /* Always close drawer on click */\n fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n filter(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\") // TODO: abstract as link click?\n if (el && isLocalLocation(el)) {\n return true\n }\n }\n return false\n })\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n })\n\n /* Enable instant loading, if not on file:// protocol */\n if (\n config.features.includes(\"navigation.instant\") &&\n location.protocol !== \"file:\"\n ) {\n const dom = new DOMParser()\n\n /* Fetch sitemap and extract URL whitelist */\n base$\n .pipe(\n switchMap(base => from(fetch(`${base}/sitemap.xml`)\n .then(res => res.text())\n .then(text => dom.parseFromString(text, \"text/xml\"))\n )),\n withLatestFrom(base$),\n map(([document, base]) => {\n const urls = getElements(\"loc\", document)\n .map(node => node.textContent!)\n\n // Hack: This is a temporary fix to normalize instant loading lookup\n // on localhost and Netlify previews. If this approach proves to be\n // suitable, we'll refactor URL whitelisting anyway. We take the two\n // shortest URLs and determine the common prefix to isolate the\n // domain. If there're no two domains, we just leave it as-is, as\n // there isn't anything to be loaded anway.\n if (urls.length > 1) {\n const [a, b] = urls.sort((a, b) => a.length - b.length)\n\n /* Determine common prefix */\n let index = 0\n if (a === b)\n index = a.length\n else\n while (a.charAt(index) === b.charAt(index))\n index++\n\n /* Replace common prefix (i.e. base) with effective base */\n for (let i = 0; i < urls.length; i++)\n urls[i] = urls[i].replace(a.slice(0, index), `${base}/`)\n }\n return urls\n })\n )\n .subscribe(urls => {\n setupInstantLoading(urls, { document$, location$, viewport$ })\n })\n }\n\n /* ----------------------------------------------------------------------- */\n\n // Make indeterminate toggles indeterminate to expand navigation on screen\n document$.subscribe(() => {\n const toggles = getElements(\"[data-md-state=indeterminate]\")\n for (const toggle of toggles) {\n toggle.dataset.mdState = \"\"\n toggle.indeterminate = true\n toggle.checked = false\n }\n })\n\n // Auto hide header - this is still experimental, so there might be some\n // opportunities for refactoring, but we'll address them when this feature\n // got some feedback from the community.\n if (config.features.includes(\"header.autohide\")) {\n viewport$\n .pipe(\n map(({ offset }) => offset.y),\n bufferCount(2, 1),\n map(([a, b]) => [a < b, b] as const),\n distinctUntilKeyChanged(0),\n switchMap(([direction, y0]) => viewport$\n .pipe(\n map(({ offset }) => offset.y),\n filter(y1 => y1 > 400),\n map(y1 => Math.abs(y0 - y1)),\n filter(y => y > 100),\n map(() => direction),\n take(1)\n )\n )\n )\n .subscribe(hide => {\n const header = getElement(\"[data-md-component=header]\")\n header?.setAttribute(\"data-md-state\", hide ? \"hidden\": \"shadow\")\n })\n }\n\n /* ----------------------------------------------------------------------- */\n\n const state = {\n\n /* Browser observables */\n document$,\n location$,\n viewport$,\n\n /* Component observables */\n header$,\n main$,\n navigation$,\n search$,\n tabs$,\n toc$,\n\n /* Integration observables */\n clipboard$,\n keyboard$,\n dialog$\n }\n\n /* Subscribe to all observables */\n merge(...Object.values(state))\n .subscribe()\n return state\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchTransformFn } from \"integrations\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flags\n */\nexport type Feature =\n | \"header.autohide\" /* Hide header */\n | \"navigation.tabs\" /* Tabs navigation */\n | \"navigation.instant\" /* Instant loading */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Feature[] /* Feature flags */\n search: {\n worker: string /* Worker URL */\n index?: Promise /* Promise resolving with index */\n transform?: SearchTransformFn /* Transformation function */\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Ensure that the given value is a valid configuration\n *\n * We could use `jsonschema` or any other schema validation framework, but that\n * would just add more bloat to the bundle, so we'll keep it plain and simple.\n *\n * @param config - Configuration\n *\n * @return Test result\n */\nexport function isConfig(config: any): config is Config {\n return typeof config === \"object\"\n && typeof config.base === \"string\"\n && typeof config.features === \"object\"\n && typeof config.search === \"object\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ReplaySubject, Subject, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch document\n *\n * Documents must be implemented as subjects, so all downstream observables are\n * automatically updated when a new document is emitted. This enabled features\n * like instant loading.\n *\n * @return Document subject\n */\nexport function watchDocument(): Subject {\n const document$ = new ReplaySubject()\n fromEvent(document, \"DOMContentLoaded\")\n .pipe(\n mapTo(document)\n )\n .subscribe(document$)\n\n /* Return document */\n return document$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { map, shareReplay, take } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n location$: Observable /* Location observable */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location base\n *\n * @return Location base observable\n */\nexport function watchLocationBase(\n base: string, { location$ }: WatchOptions\n): Observable {\n return location$\n .pipe(\n take(1),\n map(({ href }) => new URL(base, href)\n .toString()\n .replace(/\\/$/, \"\")\n ),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport { distinctUntilKeyChanged, map } from \"rxjs/operators\"\n\nimport { Viewport, getElements } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `code` elements\n *\n * This function will make overflowing code blocks focusable via keyboard, so\n * they can be scrolled without a mouse.\n *\n * @param options - Options\n */\nexport function patchCodeBlocks(\n { document$, viewport$ }: MountOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"pre > code\"))\n )\n\n /* Observe viewport size only */\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Make overflowing elements focusable */\n combineLatest([els$, size$])\n .subscribe(([els]) => {\n for (const el of els) {\n if (el.scrollWidth > el.clientWidth)\n el.setAttribute(\"tabindex\", \"0\")\n else\n el.removeAttribute(\"tabindex\")\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport {\n filter,\n map,\n switchMapTo,\n tap\n} from \"rxjs/operators\"\n\nimport {\n getElement,\n getElements,\n watchMedia\n} from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n hash$: Observable /* Location hash observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `details` elements\n *\n * This function will ensure that all `details` tags are opened prior to\n * printing, so the whole content of the page is included, and on anchor jumps.\n *\n * @param options - Options\n */\nexport function patchDetails(\n { document$, hash$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"details\"))\n )\n\n /* Open all details before printing */\n merge(\n watchMedia(\"print\").pipe(filter(Boolean)), /* Webkit */\n fromEvent(window, \"beforeprint\") /* IE, FF */\n )\n .pipe(\n switchMapTo(els$)\n )\n .subscribe(els => {\n for (const el of els)\n el.setAttribute(\"open\", \"\")\n })\n\n /* Open parent details and fix anchor jump */\n hash$\n .pipe(\n map(id => getElement(`[id=\"${id}\"]`)!),\n filter(el => typeof el !== \"undefined\"),\n tap(el => {\n const details = el.closest(\"details\")\n if (details && !details.open)\n details.setAttribute(\"open\", \"\")\n })\n )\n .subscribe(el => el.scrollIntoView())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { EMPTY, Observable, noop, of } from \"rxjs\"\nimport {\n concatMap,\n map,\n skip,\n switchMap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n createElement,\n getElements,\n replaceElement\n} from \"browser\"\nimport { useComponent } from \"components\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `script` elements\n *\n * This function must be run after a document switch, which means the first\n * emission must be ignored.\n *\n * @param options - Options\n */\nexport function patchScripts(\n { document$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n skip(1),\n withLatestFrom(useComponent(\"container\")),\n map(([, el]) => getElements(\"script\", el))\n )\n\n /* Evaluate all scripts via replacement in order */\n els$\n .pipe(\n switchMap(els => of(...els)),\n concatMap(el => {\n const script = createElement(\"script\")\n if (el.src) {\n script.src = el.src\n replaceElement(el, script)\n\n /* Complete when script is loaded */\n return new Observable(observer => {\n script.onload = () => observer.complete()\n })\n\n /* Complete immediately */\n } else {\n script.textContent = el.textContent!\n replaceElement(el, script)\n return EMPTY\n }\n })\n )\n .subscribe(noop)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { map } from \"rxjs/operators\"\n\nimport {\n createElement,\n getElements,\n replaceElement\n} from \"browser\"\nimport { renderTable } from \"templates\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `table` elements\n *\n * This function will re-render all tables by wrapping them to improve overflow\n * scrolling on smaller screen sizes.\n *\n * @param options - Options\n */\nexport function patchTables(\n { document$ }: MountOptions\n): void {\n const sentinel = createElement(\"table\")\n document$\n .pipe(\n map(() => getElements(\"table:not([class])\"))\n )\n .subscribe(els => {\n for (const el of els) {\n replaceElement(el, sentinel)\n replaceElement(sentinel, renderTable(el))\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a table inside a wrapper to improve scrolling on mobile\n *\n * @param table - Table element\n *\n * @return Element\n */\nexport function renderTable(\n table: HTMLTableElement\n) {\n return (\n
    \n
    \n {table}\n
    \n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Subject, animationFrameScheduler, noop, of } from \"rxjs\"\nimport {\n delay,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n duration?: number /* Display duration (default: 2s) */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up dialog\n *\n * @param options - Options\n *\n * @return Dialog observable\n */\nexport function setupDialog(\n { duration }: SetupOptions = {}\n): Subject {\n const dialog$ = new Subject()\n\n /* Create dialog */\n const dialog = createElement(\"div\") // TODO: improve scoping\n dialog.classList.add(\"md-dialog\", \"md-typeset\")\n\n /* Display dialog */\n dialog$\n .pipe(\n switchMap(text => of(document.body) // useComponent(\"container\")\n .pipe(\n map(container => container.appendChild(dialog)),\n observeOn(animationFrameScheduler),\n delay(1), // Strangley it doesnt work when we push things to the new animation frame...\n tap(el => {\n el.innerHTML = text\n el.setAttribute(\"data-md-state\", \"open\")\n }),\n delay(duration || 2000),\n tap(el => el.removeAttribute(\"data-md-state\")),\n delay(400),\n tap(el => {\n el.innerHTML = \"\"\n el.remove()\n })\n )\n )\n )\n .subscribe(noop)\n\n /* Return dialog */\n return dialog$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, of, pipe } from \"rxjs\"\nimport { map, switchMap } from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\nimport {\n Sidebar,\n applySidebar,\n watchSidebar\n} from \"../shared\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Navigation for [screen -]\n */\ninterface NavigationBelowScreen {} // tslint:disable-line\n\n/**\n * Navigation for [screen +]\n */\ninterface NavigationAboveScreen {\n sidebar: Sidebar /* Sidebar */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Navigation\n */\nexport type Navigation =\n | NavigationBelowScreen\n | NavigationAboveScreen\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n viewport$: Observable /* Viewport observable */\n screen$: Observable /* Screen media observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount navigation from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountNavigation(\n { header$, main$, viewport$, screen$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => screen$\n .pipe(\n switchMap(screen => {\n\n /* [screen +]: Mount navigation in sidebar */\n if (screen) {\n return watchSidebar(el, { main$, viewport$ })\n .pipe(\n applySidebar(el, { header$ }),\n map(sidebar => ({ sidebar }))\n )\n\n /* [screen -]: Mount navigation in drawer */\n } else {\n return of({})\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, combineLatest, pipe } from \"rxjs\"\nimport {\n filter,\n map,\n mapTo,\n sample,\n startWith,\n switchMap,\n take\n} from \"rxjs/operators\"\n\nimport { WorkerHandler } from \"browser\"\nimport {\n SearchMessage,\n SearchResult,\n isSearchQueryMessage,\n isSearchReadyMessage\n} from \"integrations/search\"\n\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search status\n */\nexport type SearchStatus =\n | \"waiting\" /* Search waiting for initialization */\n | \"ready\" /* Search ready */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search\n */\nexport interface Search {\n status: SearchStatus /* Search status */\n query: SearchQuery /* Search query */\n result: SearchResult[] /* Search result list */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n reset$: Observable /* Search reset observable */\n result$: Observable /* Search result observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearch(\n { rx$, tx$ }: WorkerHandler,\n { query$, reset$, result$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(() => {\n\n /* Compute search status */\n const status$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n mapTo(\"ready\"),\n startWith(\"waiting\")\n ) as Observable\n\n /* Re-emit the latest query when search is ready */\n tx$\n .pipe(\n filter(isSearchQueryMessage),\n sample(status$),\n take(1)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Combine into single observable */\n return combineLatest([status$, query$, result$, reset$])\n .pipe(\n map(([status, query, result]) => ({\n status,\n query,\n result\n }))\n )\n })\n )\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.ar.min.js b/docs/assets/javascripts/lunr/min/lunr.ar.min.js deleted file mode 100644 index 248ddc5..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.ar.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ar=function(){this.pipeline.reset(),this.pipeline.add(e.ar.trimmer,e.ar.stopWordFilter,e.ar.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ar.stemmer))},e.ar.wordCharacters="ء-ٛٱـ",e.ar.trimmer=e.trimmerSupport.generateTrimmer(e.ar.wordCharacters),e.Pipeline.registerFunction(e.ar.trimmer,"trimmer-ar"),e.ar.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ف ك ب و س ل ن ا ي ت",pre2:"ال لل",pre3:"بال وال فال تال كال ولل",pre4:"فبال كبال وبال وكال"},e.suf={suf1:"ه ك ت ن ا ي",suf2:"نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه",suf3:"تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها",suf4:"كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا"},e.patterns=JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}'),e.execArray=["cleanWord","removeDiacritics","cleanAlef","removeStopWords","normalizeHamzaAndAlef","removeStartWaw","removePre432","removeEndTaa","wordCheck"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHamzaAndAlef=function(){return e.word=e.word.replace("ؤ","ء"),e.word=e.word.replace("ئ","ء"),e.word=e.word.replace(/([\u0627])\1+/gi,"ا"),!1},e.removeEndTaa=function(){return!(e.word.length>2)||(e.word=e.word.replace(/[\u0627]$/,""),e.word=e.word.replace("ة",""),!1)},e.removeStartWaw=function(){return e.word.length>3&&"و"==e.word[0]&&"و"==e.word[1]&&(e.word=e.word.slice(1)),!1},e.removePre432=function(){var r=e.word;if(e.word.length>=7){var t=new RegExp("^("+e.pre.pre4.split(" ").join("|")+")");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=6){var c=new RegExp("^("+e.pre.pre3.split(" ").join("|")+")");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=5){var l=new RegExp("^("+e.pre.pre2.split(" ").join("|")+")");e.word=e.word.replace(l,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.patternCheck=function(r){for(var t=0;t3){var t=new RegExp("^("+e.pre.pre1.split(" ").join("|")+")");e.word=e.word.replace(t,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.removeSuf1=function(){var r=e.word;if(0==e.sufRemoved&&e.word.length>3){var t=new RegExp("("+e.suf.suf1.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.removeSuf432=function(){var r=e.word;if(e.word.length>=6){var t=new RegExp("("+e.suf.suf4.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=5){var c=new RegExp("("+e.suf.suf3.split(" ").join("|")+")$");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=4){var l=new RegExp("("+e.suf.suf2.split(" ").join("|")+")$");e.word=e.word.replace(l,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.wordCheck=function(){for(var r=(e.word,[e.removeSuf432,e.removeSuf1,e.removePre1]),t=0,c=!1;e.word.length>=7&&!e.result&&t=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.de.min.js b/docs/assets/javascripts/lunr/min/lunr.de.min.js deleted file mode 100644 index f3b5c10..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.de.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `German` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.du.min.js b/docs/assets/javascripts/lunr/min/lunr.du.min.js deleted file mode 100644 index 49a0f3f..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.du.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Dutch` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.es.min.js b/docs/assets/javascripts/lunr/min/lunr.es.min.js deleted file mode 100644 index 2989d34..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.es.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Spanish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=function(){var s=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(){if(A.out_grouping(x,97,252)){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.fi.min.js b/docs/assets/javascripts/lunr/min/lunr.fi.min.js deleted file mode 100644 index 29f5dfc..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.fi.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Finnish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.fr.min.js b/docs/assets/javascripts/lunr/min/lunr.fr.min.js deleted file mode 100644 index 68cd009..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.fr.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `French` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.hu.min.js b/docs/assets/javascripts/lunr/min/lunr.hu.min.js deleted file mode 100644 index ed9d909..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.hu.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Hungarian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.it.min.js b/docs/assets/javascripts/lunr/min/lunr.it.min.js deleted file mode 100644 index 344b6a3..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.it.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Italian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!x.eq_s(1,e)||(x.ket=x.cursor,!x.in_grouping(L,97,249)))&&(x.slice_from(r),x.cursor=n,!0)}function i(){for(var r,n,i,o,t=x.cursor;;){if(x.bra=x.cursor,r=x.find_among(h,7))switch(x.ket=x.cursor,r){case 1:x.slice_from("à");continue;case 2:x.slice_from("è");continue;case 3:x.slice_from("ì");continue;case 4:x.slice_from("ò");continue;case 5:x.slice_from("ù");continue;case 6:x.slice_from("qU");continue;case 7:if(x.cursor>=x.limit)break;x.cursor++;continue}break}for(x.cursor=t;;)for(n=x.cursor;;){if(i=x.cursor,x.in_grouping(L,97,249)){if(x.bra=x.cursor,o=x.cursor,e("u","U",i))break;if(x.cursor=o,e("i","I",i))break}if(x.cursor=i,x.cursor>=x.limit)return void(x.cursor=n);x.cursor++}}function o(e){if(x.cursor=e,!x.in_grouping(L,97,249))return!1;for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function t(){if(x.in_grouping(L,97,249)){var e=x.cursor;if(x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return o(e);x.cursor++}return!0}return o(e)}return!1}function s(){var e,r=x.cursor;if(!t()){if(x.cursor=r,!x.out_grouping(L,97,249))return;if(e=x.cursor,x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return x.cursor=e,void(x.in_grouping(L,97,249)&&x.cursor=x.limit)return;x.cursor++}k=x.cursor}function a(){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function u(){var e=x.cursor;k=x.limit,p=k,g=k,s(),x.cursor=e,a()&&(p=x.cursor,a()&&(g=x.cursor))}function c(){for(var e;;){if(x.bra=x.cursor,!(e=x.find_among(q,3)))break;switch(x.ket=x.cursor,e){case 1:x.slice_from("i");break;case 2:x.slice_from("u");break;case 3:if(x.cursor>=x.limit)return;x.cursor++}}}function w(){return k<=x.cursor}function l(){return p<=x.cursor}function m(){return g<=x.cursor}function f(){var e;if(x.ket=x.cursor,x.find_among_b(C,37)&&(x.bra=x.cursor,(e=x.find_among_b(z,5))&&w()))switch(e){case 1:x.slice_del();break;case 2:x.slice_from("e")}}function v(){var e;if(x.ket=x.cursor,!(e=x.find_among_b(S,51)))return!1;switch(x.bra=x.cursor,e){case 1:if(!m())return!1;x.slice_del();break;case 2:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del());break;case 3:if(!m())return!1;x.slice_from("log");break;case 4:if(!m())return!1;x.slice_from("u");break;case 5:if(!m())return!1;x.slice_from("ente");break;case 6:if(!w())return!1;x.slice_del();break;case 7:if(!l())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(P,4),e&&(x.bra=x.cursor,m()&&(x.slice_del(),1==e&&(x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&x.slice_del()))));break;case 8:if(!m())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(F,3),e&&(x.bra=x.cursor,1==e&&m()&&x.slice_del());break;case 9:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del())))}return!0}function b(){var e,r;x.cursor>=k&&(r=x.limit_backward,x.limit_backward=k,x.ket=x.cursor,e=x.find_among_b(W,87),e&&(x.bra=x.cursor,1==e&&x.slice_del()),x.limit_backward=r)}function d(){var e=x.limit-x.cursor;if(x.ket=x.cursor,x.in_grouping_b(y,97,242)&&(x.bra=x.cursor,w()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(1,"i")&&(x.bra=x.cursor,w()))))return void x.slice_del();x.cursor=x.limit-e}function _(){d(),x.ket=x.cursor,x.eq_s_b(1,"h")&&(x.bra=x.cursor,x.in_grouping_b(U,99,103)&&w()&&x.slice_del())}var g,p,k,h=[new r("",-1,7),new r("qu",0,6),new r("á",0,1),new r("é",0,2),new r("í",0,3),new r("ó",0,4),new r("ú",0,5)],q=[new r("",-1,3),new r("I",0,1),new r("U",0,2)],C=[new r("la",-1,-1),new r("cela",0,-1),new r("gliela",0,-1),new r("mela",0,-1),new r("tela",0,-1),new r("vela",0,-1),new r("le",-1,-1),new r("cele",6,-1),new r("gliele",6,-1),new r("mele",6,-1),new r("tele",6,-1),new r("vele",6,-1),new r("ne",-1,-1),new r("cene",12,-1),new r("gliene",12,-1),new r("mene",12,-1),new r("sene",12,-1),new r("tene",12,-1),new r("vene",12,-1),new r("ci",-1,-1),new r("li",-1,-1),new r("celi",20,-1),new r("glieli",20,-1),new r("meli",20,-1),new r("teli",20,-1),new r("veli",20,-1),new r("gli",20,-1),new r("mi",-1,-1),new r("si",-1,-1),new r("ti",-1,-1),new r("vi",-1,-1),new r("lo",-1,-1),new r("celo",31,-1),new r("glielo",31,-1),new r("melo",31,-1),new r("telo",31,-1),new r("velo",31,-1)],z=[new r("ando",-1,1),new r("endo",-1,1),new r("ar",-1,2),new r("er",-1,2),new r("ir",-1,2)],P=[new r("ic",-1,-1),new r("abil",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],F=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],S=[new r("ica",-1,1),new r("logia",-1,3),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,9),new r("anza",-1,1),new r("enza",-1,5),new r("ice",-1,1),new r("atrice",7,1),new r("iche",-1,1),new r("logie",-1,3),new r("abile",-1,1),new r("ibile",-1,1),new r("usione",-1,4),new r("azione",-1,2),new r("uzione",-1,4),new r("atore",-1,2),new r("ose",-1,1),new r("ante",-1,1),new r("mente",-1,1),new r("amente",19,7),new r("iste",-1,1),new r("ive",-1,9),new r("anze",-1,1),new r("enze",-1,5),new r("ici",-1,1),new r("atrici",25,1),new r("ichi",-1,1),new r("abili",-1,1),new r("ibili",-1,1),new r("ismi",-1,1),new r("usioni",-1,4),new r("azioni",-1,2),new r("uzioni",-1,4),new r("atori",-1,2),new r("osi",-1,1),new r("anti",-1,1),new r("amenti",-1,6),new r("imenti",-1,6),new r("isti",-1,1),new r("ivi",-1,9),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,6),new r("imento",-1,6),new r("ivo",-1,9),new r("ità",-1,8),new r("istà",-1,1),new r("istè",-1,1),new r("istì",-1,1)],W=[new r("isca",-1,1),new r("enda",-1,1),new r("ata",-1,1),new r("ita",-1,1),new r("uta",-1,1),new r("ava",-1,1),new r("eva",-1,1),new r("iva",-1,1),new r("erebbe",-1,1),new r("irebbe",-1,1),new r("isce",-1,1),new r("ende",-1,1),new r("are",-1,1),new r("ere",-1,1),new r("ire",-1,1),new r("asse",-1,1),new r("ate",-1,1),new r("avate",16,1),new r("evate",16,1),new r("ivate",16,1),new r("ete",-1,1),new r("erete",20,1),new r("irete",20,1),new r("ite",-1,1),new r("ereste",-1,1),new r("ireste",-1,1),new r("ute",-1,1),new r("erai",-1,1),new r("irai",-1,1),new r("isci",-1,1),new r("endi",-1,1),new r("erei",-1,1),new r("irei",-1,1),new r("assi",-1,1),new r("ati",-1,1),new r("iti",-1,1),new r("eresti",-1,1),new r("iresti",-1,1),new r("uti",-1,1),new r("avi",-1,1),new r("evi",-1,1),new r("ivi",-1,1),new r("isco",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("Yamo",-1,1),new r("iamo",-1,1),new r("avamo",-1,1),new r("evamo",-1,1),new r("ivamo",-1,1),new r("eremo",-1,1),new r("iremo",-1,1),new r("assimo",-1,1),new r("ammo",-1,1),new r("emmo",-1,1),new r("eremmo",54,1),new r("iremmo",54,1),new r("immo",-1,1),new r("ano",-1,1),new r("iscano",58,1),new r("avano",58,1),new r("evano",58,1),new r("ivano",58,1),new r("eranno",-1,1),new r("iranno",-1,1),new r("ono",-1,1),new r("iscono",65,1),new r("arono",65,1),new r("erono",65,1),new r("irono",65,1),new r("erebbero",-1,1),new r("irebbero",-1,1),new r("assero",-1,1),new r("essero",-1,1),new r("issero",-1,1),new r("ato",-1,1),new r("ito",-1,1),new r("uto",-1,1),new r("avo",-1,1),new r("evo",-1,1),new r("ivo",-1,1),new r("ar",-1,1),new r("ir",-1,1),new r("erà",-1,1),new r("irà",-1,1),new r("erò",-1,1),new r("irò",-1,1)],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],y=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],U=[17],x=new n;this.setCurrent=function(e){x.setCurrent(e)},this.getCurrent=function(){return x.getCurrent()},this.stem=function(){var e=x.cursor;return i(),x.cursor=e,u(),x.limit_backward=e,x.cursor=x.limit,f(),x.cursor=x.limit,v()||(x.cursor=x.limit,b()),x.cursor=x.limit,_(),x.cursor=x.limit_backward,c(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.ja.min.js b/docs/assets/javascripts/lunr/min/lunr.ja.min.js deleted file mode 100644 index 5f254eb..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.ja.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.no.min.js b/docs/assets/javascripts/lunr/min/lunr.no.min.js deleted file mode 100644 index 92bc7e4..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.no.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Norwegian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.pt.min.js b/docs/assets/javascripts/lunr/min/lunr.pt.min.js deleted file mode 100644 index 6c16996..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.pt.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Portuguese` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.ro.min.js b/docs/assets/javascripts/lunr/min/lunr.ro.min.js deleted file mode 100644 index 7277140..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.ro.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Romanian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=function(){var i=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(e,i){L.eq_s(1,e)&&(L.ket=L.cursor,L.in_grouping(W,97,259)&&L.slice_from(i))}function n(){for(var i,r;;){if(i=L.cursor,L.in_grouping(W,97,259)&&(r=L.cursor,L.bra=r,e("u","U"),L.cursor=r,e("i","I")),L.cursor=i,L.cursor>=L.limit)break;L.cursor++}}function t(){if(L.out_grouping(W,97,259)){for(;!L.in_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}return!0}function a(){if(L.in_grouping(W,97,259))for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}function o(){var e,i,r=L.cursor;if(L.in_grouping(W,97,259)){if(e=L.cursor,!t())return void(h=L.cursor);if(L.cursor=e,!a())return void(h=L.cursor)}L.cursor=r,L.out_grouping(W,97,259)&&(i=L.cursor,t()&&(L.cursor=i,L.in_grouping(W,97,259)&&L.cursor=L.limit)return!1;L.cursor++}for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!1;L.cursor++}return!0}function c(){var e=L.cursor;h=L.limit,k=h,g=h,o(),L.cursor=e,u()&&(k=L.cursor,u()&&(g=L.cursor))}function s(){for(var e;;){if(L.bra=L.cursor,e=L.find_among(z,3))switch(L.ket=L.cursor,e){case 1:L.slice_from("i");continue;case 2:L.slice_from("u");continue;case 3:if(L.cursor>=L.limit)break;L.cursor++;continue}break}}function w(){return h<=L.cursor}function m(){return k<=L.cursor}function l(){return g<=L.cursor}function f(){var e,i;if(L.ket=L.cursor,(e=L.find_among_b(C,16))&&(L.bra=L.cursor,m()))switch(e){case 1:L.slice_del();break;case 2:L.slice_from("a");break;case 3:L.slice_from("e");break;case 4:L.slice_from("i");break;case 5:i=L.limit-L.cursor,L.eq_s_b(2,"ab")||(L.cursor=L.limit-i,L.slice_from("i"));break;case 6:L.slice_from("at");break;case 7:L.slice_from("aţi")}}function p(){var e,i=L.limit-L.cursor;if(L.ket=L.cursor,(e=L.find_among_b(P,46))&&(L.bra=L.cursor,m())){switch(e){case 1:L.slice_from("abil");break;case 2:L.slice_from("ibil");break;case 3:L.slice_from("iv");break;case 4:L.slice_from("ic");break;case 5:L.slice_from("at");break;case 6:L.slice_from("it")}return _=!0,L.cursor=L.limit-i,!0}return!1}function d(){var e,i;for(_=!1;;)if(i=L.limit-L.cursor,!p()){L.cursor=L.limit-i;break}if(L.ket=L.cursor,(e=L.find_among_b(F,62))&&(L.bra=L.cursor,l())){switch(e){case 1:L.slice_del();break;case 2:L.eq_s_b(1,"ţ")&&(L.bra=L.cursor,L.slice_from("t"));break;case 3:L.slice_from("ist")}_=!0}}function b(){var e,i,r;if(L.cursor>=h){if(i=L.limit_backward,L.limit_backward=h,L.ket=L.cursor,e=L.find_among_b(q,94))switch(L.bra=L.cursor,e){case 1:if(r=L.limit-L.cursor,!L.out_grouping_b(W,97,259)&&(L.cursor=L.limit-r,!L.eq_s_b(1,"u")))break;case 2:L.slice_del()}L.limit_backward=i}}function v(){var e;L.ket=L.cursor,(e=L.find_among_b(S,5))&&(L.bra=L.cursor,w()&&1==e&&L.slice_del())}var _,g,k,h,z=[new i("",-1,3),new i("I",0,1),new i("U",0,2)],C=[new i("ea",-1,3),new i("aţia",-1,7),new i("aua",-1,2),new i("iua",-1,4),new i("aţie",-1,7),new i("ele",-1,3),new i("ile",-1,5),new i("iile",6,4),new i("iei",-1,4),new i("atei",-1,6),new i("ii",-1,4),new i("ului",-1,1),new i("ul",-1,1),new i("elor",-1,3),new i("ilor",-1,4),new i("iilor",14,4)],P=[new i("icala",-1,4),new i("iciva",-1,4),new i("ativa",-1,5),new i("itiva",-1,6),new i("icale",-1,4),new i("aţiune",-1,5),new i("iţiune",-1,6),new i("atoare",-1,5),new i("itoare",-1,6),new i("ătoare",-1,5),new i("icitate",-1,4),new i("abilitate",-1,1),new i("ibilitate",-1,2),new i("ivitate",-1,3),new i("icive",-1,4),new i("ative",-1,5),new i("itive",-1,6),new i("icali",-1,4),new i("atori",-1,5),new i("icatori",18,4),new i("itori",-1,6),new i("ători",-1,5),new i("icitati",-1,4),new i("abilitati",-1,1),new i("ivitati",-1,3),new i("icivi",-1,4),new i("ativi",-1,5),new i("itivi",-1,6),new i("icităi",-1,4),new i("abilităi",-1,1),new i("ivităi",-1,3),new i("icităţi",-1,4),new i("abilităţi",-1,1),new i("ivităţi",-1,3),new i("ical",-1,4),new i("ator",-1,5),new i("icator",35,4),new i("itor",-1,6),new i("ător",-1,5),new i("iciv",-1,4),new i("ativ",-1,5),new i("itiv",-1,6),new i("icală",-1,4),new i("icivă",-1,4),new i("ativă",-1,5),new i("itivă",-1,6)],F=[new i("ica",-1,1),new i("abila",-1,1),new i("ibila",-1,1),new i("oasa",-1,1),new i("ata",-1,1),new i("ita",-1,1),new i("anta",-1,1),new i("ista",-1,3),new i("uta",-1,1),new i("iva",-1,1),new i("ic",-1,1),new i("ice",-1,1),new i("abile",-1,1),new i("ibile",-1,1),new i("isme",-1,3),new i("iune",-1,2),new i("oase",-1,1),new i("ate",-1,1),new i("itate",17,1),new i("ite",-1,1),new i("ante",-1,1),new i("iste",-1,3),new i("ute",-1,1),new i("ive",-1,1),new i("ici",-1,1),new i("abili",-1,1),new i("ibili",-1,1),new i("iuni",-1,2),new i("atori",-1,1),new i("osi",-1,1),new i("ati",-1,1),new i("itati",30,1),new i("iti",-1,1),new i("anti",-1,1),new i("isti",-1,3),new i("uti",-1,1),new i("işti",-1,3),new i("ivi",-1,1),new i("ităi",-1,1),new i("oşi",-1,1),new i("ităţi",-1,1),new i("abil",-1,1),new i("ibil",-1,1),new i("ism",-1,3),new i("ator",-1,1),new i("os",-1,1),new i("at",-1,1),new i("it",-1,1),new i("ant",-1,1),new i("ist",-1,3),new i("ut",-1,1),new i("iv",-1,1),new i("ică",-1,1),new i("abilă",-1,1),new i("ibilă",-1,1),new i("oasă",-1,1),new i("ată",-1,1),new i("ită",-1,1),new i("antă",-1,1),new i("istă",-1,3),new i("ută",-1,1),new i("ivă",-1,1)],q=[new i("ea",-1,1),new i("ia",-1,1),new i("esc",-1,1),new i("ăsc",-1,1),new i("ind",-1,1),new i("ând",-1,1),new i("are",-1,1),new i("ere",-1,1),new i("ire",-1,1),new i("âre",-1,1),new i("se",-1,2),new i("ase",10,1),new i("sese",10,2),new i("ise",10,1),new i("use",10,1),new i("âse",10,1),new i("eşte",-1,1),new i("ăşte",-1,1),new i("eze",-1,1),new i("ai",-1,1),new i("eai",19,1),new i("iai",19,1),new i("sei",-1,2),new i("eşti",-1,1),new i("ăşti",-1,1),new i("ui",-1,1),new i("ezi",-1,1),new i("âi",-1,1),new i("aşi",-1,1),new i("seşi",-1,2),new i("aseşi",29,1),new i("seseşi",29,2),new i("iseşi",29,1),new i("useşi",29,1),new i("âseşi",29,1),new i("işi",-1,1),new i("uşi",-1,1),new i("âşi",-1,1),new i("aţi",-1,2),new i("eaţi",38,1),new i("iaţi",38,1),new i("eţi",-1,2),new i("iţi",-1,2),new i("âţi",-1,2),new i("arăţi",-1,1),new i("serăţi",-1,2),new i("aserăţi",45,1),new i("seserăţi",45,2),new i("iserăţi",45,1),new i("userăţi",45,1),new i("âserăţi",45,1),new i("irăţi",-1,1),new i("urăţi",-1,1),new i("ârăţi",-1,1),new i("am",-1,1),new i("eam",54,1),new i("iam",54,1),new i("em",-1,2),new i("asem",57,1),new i("sesem",57,2),new i("isem",57,1),new i("usem",57,1),new i("âsem",57,1),new i("im",-1,2),new i("âm",-1,2),new i("ăm",-1,2),new i("arăm",65,1),new i("serăm",65,2),new i("aserăm",67,1),new i("seserăm",67,2),new i("iserăm",67,1),new i("userăm",67,1),new i("âserăm",67,1),new i("irăm",65,1),new i("urăm",65,1),new i("ârăm",65,1),new i("au",-1,1),new i("eau",76,1),new i("iau",76,1),new i("indu",-1,1),new i("ându",-1,1),new i("ez",-1,1),new i("ească",-1,1),new i("ară",-1,1),new i("seră",-1,2),new i("aseră",84,1),new i("seseră",84,2),new i("iseră",84,1),new i("useră",84,1),new i("âseră",84,1),new i("iră",-1,1),new i("ură",-1,1),new i("âră",-1,1),new i("ează",-1,1)],S=[new i("a",-1,1),new i("e",-1,1),new i("ie",1,1),new i("i",-1,1),new i("ă",-1,1)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var e=L.cursor;return n(),L.cursor=e,c(),L.limit_backward=e,L.cursor=L.limit,f(),L.cursor=L.limit,d(),L.cursor=L.limit,_||(L.cursor=L.limit,b(),L.cursor=L.limit),v(),L.cursor=L.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.ru.min.js b/docs/assets/javascripts/lunr/min/lunr.ru.min.js deleted file mode 100644 index 186cc48..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.ru.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Russian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.sv.min.js b/docs/assets/javascripts/lunr/min/lunr.sv.min.js deleted file mode 100644 index 3e5eb64..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.sv.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Swedish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.tr.min.js b/docs/assets/javascripts/lunr/min/lunr.tr.min.js deleted file mode 100644 index 563f6ec..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.tr.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Lunr languages, `Turkish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ - -!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=function(){var i=r.stemmerSupport.Among,e=r.stemmerSupport.SnowballProgram,n=new function(){function r(r,i,e){for(;;){var n=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(r,i,e)){Dr.cursor=Dr.limit-n;break}if(Dr.cursor=Dr.limit-n,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function n(){var i,e;i=Dr.limit-Dr.cursor,r(Wr,97,305);for(var n=0;nDr.limit_backward&&(Dr.cursor--,e=Dr.limit-Dr.cursor,i()))?(Dr.cursor=Dr.limit-e,!0):(Dr.cursor=Dr.limit-n,r()?(Dr.cursor=Dr.limit-n,!1):(Dr.cursor=Dr.limit-n,!(Dr.cursor<=Dr.limit_backward)&&(Dr.cursor--,!!i()&&(Dr.cursor=Dr.limit-n,!0))))}function u(r){return t(r,function(){return Dr.in_grouping_b(Wr,97,305)})}function o(){return u(function(){return Dr.eq_s_b(1,"n")})}function s(){return u(function(){return Dr.eq_s_b(1,"s")})}function c(){return u(function(){return Dr.eq_s_b(1,"y")})}function l(){return t(function(){return Dr.in_grouping_b(Lr,105,305)},function(){return Dr.out_grouping_b(Wr,97,305)})}function a(){return Dr.find_among_b(ur,10)&&l()}function m(){return n()&&Dr.in_grouping_b(Lr,105,305)&&s()}function d(){return Dr.find_among_b(or,2)}function f(){return n()&&Dr.in_grouping_b(Lr,105,305)&&c()}function b(){return n()&&Dr.find_among_b(sr,4)}function w(){return n()&&Dr.find_among_b(cr,4)&&o()}function _(){return n()&&Dr.find_among_b(lr,2)&&c()}function k(){return n()&&Dr.find_among_b(ar,2)}function p(){return n()&&Dr.find_among_b(mr,4)}function g(){return n()&&Dr.find_among_b(dr,2)}function y(){return n()&&Dr.find_among_b(fr,4)}function z(){return n()&&Dr.find_among_b(br,2)}function v(){return n()&&Dr.find_among_b(wr,2)&&c()}function h(){return Dr.eq_s_b(2,"ki")}function q(){return n()&&Dr.find_among_b(_r,2)&&o()}function C(){return n()&&Dr.find_among_b(kr,4)&&c()}function P(){return n()&&Dr.find_among_b(pr,4)}function F(){return n()&&Dr.find_among_b(gr,4)&&c()}function S(){return Dr.find_among_b(yr,4)}function W(){return n()&&Dr.find_among_b(zr,2)}function L(){return n()&&Dr.find_among_b(vr,4)}function x(){return n()&&Dr.find_among_b(hr,8)}function A(){return Dr.find_among_b(qr,2)}function E(){return n()&&Dr.find_among_b(Cr,32)&&c()}function j(){return Dr.find_among_b(Pr,8)&&c()}function T(){return n()&&Dr.find_among_b(Fr,4)&&c()}function Z(){return Dr.eq_s_b(3,"ken")&&c()}function B(){var r=Dr.limit-Dr.cursor;return!(T()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,Z()))))}function D(){if(A()){var r=Dr.limit-Dr.cursor;if(S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T())return!1}return!0}function G(){if(W()){Dr.bra=Dr.cursor,Dr.slice_del();var r=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,x()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,T()||(Dr.cursor=Dr.limit-r)))),nr=!1,!1}return!0}function H(){if(!L())return!0;var r=Dr.limit-Dr.cursor;return!E()&&(Dr.cursor=Dr.limit-r,!j())}function I(){var r,i=Dr.limit-Dr.cursor;return!(S()||(Dr.cursor=Dr.limit-i,F()||(Dr.cursor=Dr.limit-i,P()||(Dr.cursor=Dr.limit-i,C()))))||(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,T()||(Dr.cursor=Dr.limit-r),!1)}function J(){var r,i=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,nr=!0,B()&&(Dr.cursor=Dr.limit-i,D()&&(Dr.cursor=Dr.limit-i,G()&&(Dr.cursor=Dr.limit-i,H()&&(Dr.cursor=Dr.limit-i,I()))))){if(Dr.cursor=Dr.limit-i,!x())return;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T()||(Dr.cursor=Dr.limit-r)}Dr.bra=Dr.cursor,Dr.slice_del()}function K(){var r,i,e,n;if(Dr.ket=Dr.cursor,h()){if(r=Dr.limit-Dr.cursor,p())return Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,a()&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))),!0;if(Dr.cursor=Dr.limit-r,w()){if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,e=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-e,!m()&&(Dr.cursor=Dr.limit-e,!K())))return!0;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}return!0}if(Dr.cursor=Dr.limit-r,g()){if(n=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-n,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-n,!K())return!1;return!0}}return!1}function M(r){if(Dr.ket=Dr.cursor,!g()&&(Dr.cursor=Dr.limit-r,!k()))return!1;var i=Dr.limit-Dr.cursor;if(d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-i,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-i,!K())return!1;return!0}function N(r){if(Dr.ket=Dr.cursor,!z()&&(Dr.cursor=Dr.limit-r,!b()))return!1;var i=Dr.limit-Dr.cursor;return!(!m()&&(Dr.cursor=Dr.limit-i,!d()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)}function O(){var r,i=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,!(!w()&&(Dr.cursor=Dr.limit-i,!v()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,!(!W()||(Dr.bra=Dr.cursor,Dr.slice_del(),!K()))||(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!(a()||(Dr.cursor=Dr.limit-r,m()||(Dr.cursor=Dr.limit-r,K())))||(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)))}function Q(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,!p()&&(Dr.cursor=Dr.limit-e,!f()&&(Dr.cursor=Dr.limit-e,!_())))return!1;if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,a())Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()||(Dr.cursor=Dr.limit-i);else if(Dr.cursor=Dr.limit-r,!W())return!0;return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,K(),!0}function R(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,W())return Dr.bra=Dr.cursor,Dr.slice_del(),void K();if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,q())if(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-r,!m())){if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!W())return;if(Dr.bra=Dr.cursor,Dr.slice_del(),!K())return}Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}else if(Dr.cursor=Dr.limit-e,!M(e)&&(Dr.cursor=Dr.limit-e,!N(e))){if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,y())return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,i=Dr.limit-Dr.cursor,void(a()?(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())):(Dr.cursor=Dr.limit-i,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,K())));if(Dr.cursor=Dr.limit-e,!O()){if(Dr.cursor=Dr.limit-e,d())return Dr.bra=Dr.cursor,void Dr.slice_del();Dr.cursor=Dr.limit-e,K()||(Dr.cursor=Dr.limit-e,Q()||(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,(a()||(Dr.cursor=Dr.limit-e,m()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))))}}}function U(){var r;if(Dr.ket=Dr.cursor,r=Dr.find_among_b(Sr,4))switch(Dr.bra=Dr.cursor,r){case 1:Dr.slice_from("p");break;case 2:Dr.slice_from("ç");break;case 3:Dr.slice_from("t");break;case 4:Dr.slice_from("k")}}function V(){for(;;){var r=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(Wr,97,305)){Dr.cursor=Dr.limit-r;break}if(Dr.cursor=Dr.limit-r,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function X(r,i,e){if(Dr.cursor=Dr.limit-r,V()){var n=Dr.limit-Dr.cursor;if(!Dr.eq_s_b(1,i)&&(Dr.cursor=Dr.limit-n,!Dr.eq_s_b(1,e)))return!0;Dr.cursor=Dr.limit-r;var t=Dr.cursor;return Dr.insert(Dr.cursor,Dr.cursor,e),Dr.cursor=t,!1}return!0}function Y(){var r=Dr.limit-Dr.cursor;(Dr.eq_s_b(1,"d")||(Dr.cursor=Dr.limit-r,Dr.eq_s_b(1,"g")))&&X(r,"a","ı")&&X(r,"e","i")&&X(r,"o","u")&&X(r,"ö","ü")}function $(){for(var r,i=Dr.cursor,e=2;;){for(r=Dr.cursor;!Dr.in_grouping(Wr,97,305);){if(Dr.cursor>=Dr.limit)return Dr.cursor=r,!(e>0)&&(Dr.cursor=i,!0);Dr.cursor++}e--}}function rr(r,i,e){for(;!Dr.eq_s(i,e);){if(Dr.cursor>=Dr.limit)return!0;Dr.cursor++}return(tr=i)!=Dr.limit||(Dr.cursor=r,!1)}function ir(){var r=Dr.cursor;return!rr(r,2,"ad")||(Dr.cursor=r,!rr(r,5,"soyad"))}function er(){var r=Dr.cursor;return!ir()&&(Dr.limit_backward=r,Dr.cursor=Dr.limit,Y(),Dr.cursor=Dr.limit,U(),!0)}var nr,tr,ur=[new i("m",-1,-1),new i("n",-1,-1),new i("miz",-1,-1),new i("niz",-1,-1),new i("muz",-1,-1),new i("nuz",-1,-1),new i("müz",-1,-1),new i("nüz",-1,-1),new i("mız",-1,-1),new i("nız",-1,-1)],or=[new i("leri",-1,-1),new i("ları",-1,-1)],sr=[new i("ni",-1,-1),new i("nu",-1,-1),new i("nü",-1,-1),new i("nı",-1,-1)],cr=[new i("in",-1,-1),new i("un",-1,-1),new i("ün",-1,-1),new i("ın",-1,-1)],lr=[new i("a",-1,-1),new i("e",-1,-1)],ar=[new i("na",-1,-1),new i("ne",-1,-1)],mr=[new i("da",-1,-1),new i("ta",-1,-1),new i("de",-1,-1),new i("te",-1,-1)],dr=[new i("nda",-1,-1),new i("nde",-1,-1)],fr=[new i("dan",-1,-1),new i("tan",-1,-1),new i("den",-1,-1),new i("ten",-1,-1)],br=[new i("ndan",-1,-1),new i("nden",-1,-1)],wr=[new i("la",-1,-1),new i("le",-1,-1)],_r=[new i("ca",-1,-1),new i("ce",-1,-1)],kr=[new i("im",-1,-1),new i("um",-1,-1),new i("üm",-1,-1),new i("ım",-1,-1)],pr=[new i("sin",-1,-1),new i("sun",-1,-1),new i("sün",-1,-1),new i("sın",-1,-1)],gr=[new i("iz",-1,-1),new i("uz",-1,-1),new i("üz",-1,-1),new i("ız",-1,-1)],yr=[new i("siniz",-1,-1),new i("sunuz",-1,-1),new i("sünüz",-1,-1),new i("sınız",-1,-1)],zr=[new i("lar",-1,-1),new i("ler",-1,-1)],vr=[new i("niz",-1,-1),new i("nuz",-1,-1),new i("nüz",-1,-1),new i("nız",-1,-1)],hr=[new i("dir",-1,-1),new i("tir",-1,-1),new i("dur",-1,-1),new i("tur",-1,-1),new i("dür",-1,-1),new i("tür",-1,-1),new i("dır",-1,-1),new i("tır",-1,-1)],qr=[new i("casına",-1,-1),new i("cesine",-1,-1)],Cr=[new i("di",-1,-1),new i("ti",-1,-1),new i("dik",-1,-1),new i("tik",-1,-1),new i("duk",-1,-1),new i("tuk",-1,-1),new i("dük",-1,-1),new i("tük",-1,-1),new i("dık",-1,-1),new i("tık",-1,-1),new i("dim",-1,-1),new i("tim",-1,-1),new i("dum",-1,-1),new i("tum",-1,-1),new i("düm",-1,-1),new i("tüm",-1,-1),new i("dım",-1,-1),new i("tım",-1,-1),new i("din",-1,-1),new i("tin",-1,-1),new i("dun",-1,-1),new i("tun",-1,-1),new i("dün",-1,-1),new i("tün",-1,-1),new i("dın",-1,-1),new i("tın",-1,-1),new i("du",-1,-1),new i("tu",-1,-1),new i("dü",-1,-1),new i("tü",-1,-1),new i("dı",-1,-1),new i("tı",-1,-1)],Pr=[new i("sa",-1,-1),new i("se",-1,-1),new i("sak",-1,-1),new i("sek",-1,-1),new i("sam",-1,-1),new i("sem",-1,-1),new i("san",-1,-1),new i("sen",-1,-1)],Fr=[new i("miş",-1,-1),new i("muş",-1,-1),new i("müş",-1,-1),new i("mış",-1,-1)],Sr=[new i("b",-1,1),new i("c",-1,2),new i("d",-1,3),new i("ğ",-1,4)],Wr=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],Lr=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],xr=[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],Ar=[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],Er=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],jr=[17],Tr=[65],Zr=[65],Br=[["a",xr,97,305],["e",Ar,101,252],["ı",Er,97,305],["i",jr,101,105],["o",Tr,111,117],["ö",Zr,246,252],["u",Tr,111,117]],Dr=new e;this.setCurrent=function(r){Dr.setCurrent(r)},this.getCurrent=function(){return Dr.getCurrent()},this.stem=function(){return!!($()&&(Dr.limit_backward=Dr.cursor,Dr.cursor=Dr.limit,J(),Dr.cursor=Dr.limit,nr&&(R(),Dr.cursor=Dr.limit_backward,er())))}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.tr.stemmer,"stemmer-tr"),r.tr.stopWordFilter=r.generateStopWordFilter("acaba altmış altı ama ancak arada aslında ayrıca bana bazı belki ben benden beni benim beri beş bile bin bir biri birkaç birkez birçok birşey birşeyi biz bizden bize bizi bizim bu buna bunda bundan bunlar bunları bunların bunu bunun burada böyle böylece da daha dahi de defa değil diye diğer doksan dokuz dolayı dolayısıyla dört edecek eden ederek edilecek ediliyor edilmesi ediyor elli en etmesi etti ettiği ettiğini eğer gibi göre halen hangi hatta hem henüz hep hepsi her herhangi herkesin hiç hiçbir iki ile ilgili ise itibaren itibariyle için işte kadar karşın katrilyon kendi kendilerine kendini kendisi kendisine kendisini kez ki kim kimden kime kimi kimse kırk milyar milyon mu mü mı nasıl ne neden nedenle nerde nerede nereye niye niçin o olan olarak oldu olduklarını olduğu olduğunu olmadı olmadığı olmak olması olmayan olmaz olsa olsun olup olur olursa oluyor on ona ondan onlar onlardan onları onların onu onun otuz oysa pek rağmen sadece sanki sekiz seksen sen senden seni senin siz sizden sizi sizin tarafından trilyon tüm var vardı ve veya ya yani yapacak yapmak yaptı yaptıkları yaptığı yaptığını yapılan yapılması yapıyor yedi yerine yetmiş yine yirmi yoksa yüz zaten çok çünkü öyle üzere üç şey şeyden şeyi şeyler şu şuna şunda şundan şunları şunu şöyle".split(" ")),r.Pipeline.registerFunction(r.tr.stopWordFilter,"stopWordFilter-tr")}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/min/lunr.vi.min.js b/docs/assets/javascripts/lunr/min/lunr.vi.min.js deleted file mode 100644 index 22aed28..0000000 --- a/docs/assets/javascripts/lunr/min/lunr.vi.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); \ No newline at end of file diff --git a/docs/assets/javascripts/lunr/tinyseg.min.js b/docs/assets/javascripts/lunr/tinyseg.min.js deleted file mode 100644 index 302befb..0000000 --- a/docs/assets/javascripts/lunr/tinyseg.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(_,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(_.lunr)}(this,(function(){return function(_){function t(){var _={"[一二三四五六七八九十百千万億兆]":"M","[一-龠々〆ヵヶ]":"H","[ぁ-ん]":"I","[ァ-ヴーア-ン゙ー]":"K","[a-zA-Za-zA-Z]":"A","[0-90-9]":"N"};for(var t in this.chartype_=[],_){var H=new RegExp(t);this.chartype_.push([H,_[t]])}return this.BIAS__=-332,this.BC1__={HH:6,II:2461,KH:406,OH:-1378},this.BC2__={AA:-3267,AI:2744,AN:-878,HH:-4070,HM:-1711,HN:4012,HO:3761,IA:1327,IH:-1184,II:-1332,IK:1721,IO:5492,KI:3831,KK:-8741,MH:-3132,MK:3334,OO:-2920},this.BC3__={HH:996,HI:626,HK:-721,HN:-1307,HO:-836,IH:-301,KK:2762,MK:1079,MM:4034,OA:-1652,OH:266},this.BP1__={BB:295,OB:304,OO:-125,UB:352},this.BP2__={BO:60,OO:-1762},this.BQ1__={BHH:1150,BHM:1521,BII:-1158,BIM:886,BMH:1208,BNH:449,BOH:-91,BOO:-2597,OHI:451,OIH:-296,OKA:1851,OKH:-1020,OKK:904,OOO:2965},this.BQ2__={BHH:118,BHI:-1159,BHM:466,BIH:-919,BKK:-1720,BKO:864,OHH:-1139,OHM:-181,OIH:153,UHI:-1146},this.BQ3__={BHH:-792,BHI:2664,BII:-299,BKI:419,BMH:937,BMM:8335,BNN:998,BOH:775,OHH:2174,OHM:439,OII:280,OKH:1798,OKI:-793,OKO:-2242,OMH:-2402,OOO:11699},this.BQ4__={BHH:-3895,BIH:3761,BII:-4654,BIK:1348,BKK:-1806,BMI:-3385,BOO:-12396,OAH:926,OHH:266,OHK:-2036,ONN:-973},this.BW1__={",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682},this.BW2__={"..":-11822,11:-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669},this.BW3__={"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1e3,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990},this.TC1__={AAA:1093,HHH:1029,HHM:580,HII:998,HOH:-390,HOM:-331,IHI:1169,IOH:-142,IOI:-1015,IOM:467,MMH:187,OOI:-1832},this.TC2__={HHO:2088,HII:-1023,HMM:-1154,IHI:-1965,KKH:703,OII:-2649},this.TC3__={AAA:-294,HHH:346,HHI:-341,HII:-1088,HIK:731,HOH:-1486,IHH:128,IHI:-3041,IHO:-1935,IIH:-825,IIM:-1035,IOI:-542,KHH:-1216,KKA:491,KKH:-1217,KOK:-1009,MHH:-2694,MHM:-457,MHO:123,MMH:-471,NNH:-1689,NNO:662,OHO:-3393},this.TC4__={HHH:-203,HHI:1344,HHK:365,HHM:-122,HHN:182,HHO:669,HIH:804,HII:679,HOH:446,IHH:695,IHO:-2324,IIH:321,III:1497,IIO:656,IOO:54,KAK:4845,KKA:3386,KKK:3065,MHH:-405,MHI:201,MMH:-241,MMM:661,MOM:841},this.TQ1__={BHHH:-227,BHHI:316,BHIH:-132,BIHH:60,BIII:1595,BNHH:-744,BOHH:225,BOOO:-908,OAKK:482,OHHH:281,OHIH:249,OIHI:200,OIIH:-68},this.TQ2__={BIHH:-1401,BIII:-1033,BKAK:-543,BOOO:-5591},this.TQ3__={BHHH:478,BHHM:-1073,BHIH:222,BHII:-504,BIIH:-116,BIII:-105,BMHI:-863,BMHM:-464,BOMH:620,OHHH:346,OHHI:1729,OHII:997,OHMH:481,OIHH:623,OIIH:1344,OKAK:2792,OKHH:587,OKKA:679,OOHH:110,OOII:-685},this.TQ4__={BHHH:-721,BHHM:-3604,BHII:-966,BIIH:-607,BIII:-2181,OAAA:-2763,OAKK:180,OHHH:-294,OHHI:2446,OHHO:480,OHIH:-1573,OIHH:1935,OIHI:-493,OIIH:626,OIII:-4007,OKAK:-8156},this.TW1__={"につい":-4681,"東京都":2026},this.TW2__={"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216},this.TW3__={"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287},this.TW4__={"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865},this.UC1__={A:484,K:93,M:645,O:-505},this.UC2__={A:819,H:1059,I:409,M:3987,N:5775,O:646},this.UC3__={A:-1370,I:2311},this.UC4__={A:-2643,H:1809,I:-1032,K:-3450,M:3565,N:3876,O:6646},this.UC5__={H:313,I:-1238,K:-799,M:539,O:-831},this.UC6__={H:-506,I:-253,K:87,M:247,O:-387},this.UP1__={O:-214},this.UP2__={B:69,O:935},this.UP3__={B:189},this.UQ1__={BH:21,BI:-12,BK:-99,BN:142,BO:-56,OH:-95,OI:477,OK:410,OO:-2422},this.UQ2__={BH:216,BI:113,OK:1759},this.UQ3__={BA:-479,BH:42,BI:1913,BK:-7198,BM:3160,BN:6427,BO:14761,OI:-827,ON:-3212},this.UW1__={",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135},this.UW2__={",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568},this.UW3__={",":4889,1:-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278},this.UW4__={",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1e3,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637},this.UW5__={",":465,".":-299,1:-514,E2:-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343},this.UW6__={",":227,".":808,1:-270,E1:306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496},this}t.prototype.ctype_=function(_){for(var t in this.chartype_)if(_.match(this.chartype_[t][0]))return this.chartype_[t][1];return"O"},t.prototype.ts_=function(_){return _||0},t.prototype.segment=function(_){if(null==_||null==_||""==_)return[];var t=[],H=["B3","B2","B1"],s=["O","O","O"],h=_.split("");for(K=0;K0&&(t.push(i),i="",N="B"),I=O,O=B,B=N,i+=H[K]}return t.push(i),t},_.TinySegmenter=t}})); \ No newline at end of file diff --git a/docs/assets/javascripts/vendor.08c56446.min.js b/docs/assets/javascripts/vendor.08c56446.min.js deleted file mode 100644 index 2933664..0000000 --- a/docs/assets/javascripts/vendor.08c56446.min.js +++ /dev/null @@ -1,16 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(t,e,n){"use strict";n.d(e,"a",(function(){return i})),n.d(e,"b",(function(){return o}));var r=n(2);function i(t){return Object(r.a)(null==t?void 0:t.lift)}function o(t){return e=>{if(i(e))return e.lift((function(e){try{return t(e,this)}catch(t){this.error(t)}}));throw new TypeError("Unable to lift unknown Observable type")}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(16);class i extends r.b{constructor(t,e,n,r,i){super(t),this.onUnsubscribe=i,e&&(this._next=function(t){try{e(t)}catch(t){this.destination.error(t)}}),n&&(this._error=function(t){try{n(t)}catch(t){this.destination.error(t)}this.unsubscribe()}),r&&(this._complete=function(){try{r()}catch(t){this.destination.error(t)}this.unsubscribe()})}unsubscribe(){var t;!this.closed&&(null===(t=this.onUnsubscribe)||void 0===t||t.call(this)),super.unsubscribe()}}},function(t,e,n){"use strict";function r(t){return"function"==typeof t}n.d(e,"a",(function(){return r}))},,,function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(16),i=n(7),o=n(14),s=n(39),c=n(11),u=n(2);class a{constructor(t){t&&(this._subscribe=t)}lift(t){const e=new a;return e.source=this,e.operator=t,e}subscribe(t,e,n){const o=(s=t)&&s instanceof r.b||function(t){return t&&Object(u.a)(t.next)&&Object(u.a)(t.error)&&Object(u.a)(t.complete)}(s)&&Object(i.c)(s)?t:new r.a(t,e,n);var s;const{operator:a,source:l}=this;return o.add(a?a.call(o,l):l||c.a.useDeprecatedSynchronousErrorHandling?this._subscribe(o):this._trySubscribe(o)),o}_trySubscribe(t){try{return this._subscribe(t)}catch(e){if(c.a.useDeprecatedSynchronousErrorHandling)throw e;t.error(e)}}forEach(t,e){return new(e=l(e))((e,n)=>{let r;r=this.subscribe(e=>{try{t(e)}catch(t){n(t),null==r||r.unsubscribe()}},n,e)})}_subscribe(t){var e;return null===(e=this.source)||void 0===e?void 0:e.subscribe(t)}[o.a](){return this}pipe(...t){return t.length?Object(s.b)(t)(this):this}toPromise(t){return new(t=l(t))((t,e)=>{let n;this.subscribe(t=>n=t,t=>e(t),()=>t(n))})}}function l(t){var e;return null!==(e=null!=t?t:c.a.Promise)&&void 0!==e?e:Promise}a.create=t=>new a(t)},function(t,e,n){"use strict";n.d(e,"a",(function(){return g})),n.d(e,"c",(function(){return _})),n.d(e,"b",(function(){return O}));function r(t,e,n,r){return new(n||(n=Promise))((function(i,o){function s(t){try{u(r.next(t))}catch(t){o(t)}}function c(t){try{u(r.throw(t))}catch(t){o(t)}}function u(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(s,c)}u((r=r.apply(t,e||[])).next())}))}Object.create;function i(t){var e="function"==typeof Symbol&&Symbol.iterator,n=e&&t[e],r=0;if(n)return n.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function o(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,n=t[Symbol.asyncIterator];return n?n.call(t):(t=i(t),e={},r("next"),r("throw"),r("return"),e[Symbol.asyncIterator]=function(){return this},e);function r(n){e[n]=t[n]&&function(e){return new Promise((function(r,i){(function(t,e,n,r){Promise.resolve(r).then((function(e){t({value:e,done:n})}),e)})(r,i,(e=t[n](e)).done,e.value)}))}}}Object.create;var s=n(17),c=n(2);function u(t){return Object(c.a)(null==t?void 0:t.then)}const a="function"==typeof Symbol&&Symbol.iterator?Symbol.iterator:"@@iterator";var l=n(14),d=n(5),f=n(7);var h=n(18);function b(t){return Object(c.a)(t[l.a])}function v(t){return Object(c.a)(null==t?void 0:t[a])}function p(t){return Symbol.asyncIterator&&Object(c.a)(null==t?void 0:t[Symbol.asyncIterator])}function m(t){return new TypeError(`You provided ${null!==t&&"object"==typeof t?"an invalid object":`'${t}'`} where a stream was expected. You can provide an Observable, Promise, Array, AsyncIterable, or Iterable.`)}function y(t,e){if(null!=t){if(b(t))return function(t,e){return new d.a(n=>{const r=new f.b;return r.add(e.schedule(()=>{const i=t[l.a]();r.add(i.subscribe({next(t){r.add(e.schedule(()=>n.next(t)))},error(t){r.add(e.schedule(()=>n.error(t)))},complete(){r.add(e.schedule(()=>n.complete()))}}))})),r})}(t,e);if(Object(s.a)(t))return Object(h.a)(t,e);if(u(t))return function(t,e){return new d.a(n=>e.schedule(()=>t.then(t=>{n.add(e.schedule(()=>{n.next(t),n.add(e.schedule(()=>n.complete()))}))},t=>{n.add(e.schedule(()=>n.error(t)))})))}(t,e);if(p(t))return function(t,e){if(!t)throw new Error("Iterable cannot be null");return new d.a(n=>{const r=new f.b;return r.add(e.schedule(()=>{const i=t[Symbol.asyncIterator]();r.add(e.schedule((function(){i.next().then(t=>{t.done?n.complete():(n.next(t.value),this.schedule())})})))})),r})}(t,e);if(v(t))return function(t,e){return new d.a(n=>{let r;return n.add(e.schedule(()=>{r=t[a](),function(t,e,n,r=0){const i=e.schedule((function(){try{n.call(this)}catch(e){t.error(e)}}),r);t.add(i)}(n,e,(function(){const{value:t,done:e}=r.next();e?n.complete():(n.next(t),this.schedule())}))})),()=>Object(c.a)(null==r?void 0:r.return)&&r.return()})}(t,e)}throw m(t)}var w=n(24);function g(t,e){return e?y(t,e):_(t)}function _(t){if(t instanceof d.a)return t;if(null!=t){if(b(t))return f=t,new d.a(t=>{const e=f[l.a]();if(Object(c.a)(e.subscribe))return e.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")});if(Object(s.a)(t))return O(t);if(u(t))return i=t,new d.a(t=>{i.then(e=>{t.closed||(t.next(e),t.complete())},e=>t.error(e)).then(null,w.a)});if(p(t))return n=t,new d.a(t=>{(function(t,e){var n,i,s,c;return r(this,void 0,void 0,(function*(){try{for(n=o(t);!(i=yield n.next()).done;){const t=i.value;e.next(t)}}catch(t){s={error:t}}finally{try{i&&!i.done&&(c=n.return)&&(yield c.call(n))}finally{if(s)throw s.error}}e.complete()}))})(n,t).catch(e=>t.error(e))});if(v(t))return e=t,new d.a(t=>{const n=e[a]();for(;!t.closed;){const{done:e,value:r}=n.next();e?t.complete():t.next(r)}return()=>Object(c.a)(null==n?void 0:n.return)&&n.return()})}var e,n,i,f;throw m(t)}function O(t){return new d.a(e=>{for(let n=0;nfunction(e){t(this),this.message=e?`${e.length} errors occurred during unsubscription:\n${e.map((t,e)=>`${e+1}) ${t.toString()}`).join("\n ")}`:"",this.name="UnsubscriptionError",this.errors=e});var s=n(12);class c{constructor(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._teardowns=null}unsubscribe(){let t;if(!this.closed){this.closed=!0;const{_parentage:e}=this;if(Array.isArray(e))for(const t of e)t.remove(this);else null==e||e.remove(this);const{initialTeardown:n}=this;if(Object(r.a)(n))try{n()}catch(e){t=e instanceof o?e.errors:[e]}const{_teardowns:i}=this;if(i){this._teardowns=null;for(const e of i)try{l(e)}catch(e){t=null!=t?t:[],e instanceof o?t=[...t,...e.errors]:t.push(e)}}if(t)throw new o(t)}}add(t){var e;if(t&&t!==this)if(this.closed)l(t);else{if(t instanceof c){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._teardowns=null!==(e=this._teardowns)&&void 0!==e?e:[]).push(t)}}_hasParent(t){const{_parentage:e}=this;return e===t||Array.isArray(e)&&e.includes(t)}_addParent(t){const{_parentage:e}=this;this._parentage=Array.isArray(e)?(e.push(t),e):e?[e,t]:t}_removeParent(t){const{_parentage:e}=this;e===t?this._parentage=null:Array.isArray(e)&&Object(s.a)(e,t)}remove(t){const{_teardowns:e}=this;e&&Object(s.a)(e,t),t instanceof c&&t._removeParent(this)}}c.EMPTY=(()=>{const t=new c;return t.closed=!0,t})();const u=c.EMPTY;function a(t){return t instanceof c||t&&"closed"in t&&Object(r.a)(t.remove)&&Object(r.a)(t.add)&&Object(r.a)(t.unsubscribe)}function l(t){Object(r.a)(t)?t():t.unsubscribe()}},function(t,e,n){"use strict";n.d(e,"b",(function(){return s})),n.d(e,"c",(function(){return c})),n.d(e,"a",(function(){return u}));var r=n(2),i=n(29);function o(t){return t[t.length-1]}function s(t){return Object(r.a)(o(t))?t.pop():void 0}function c(t){return Object(i.a)(o(t))?t.pop():void 0}function u(t,e){return"number"==typeof o(t)?t.pop():e}},function(t,e,n){"use strict";function r(){}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";function r(t){return t}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1}},function(t,e,n){"use strict";function r(t,e){if(t){const n=t.indexOf(e);0<=n&&t.splice(n,1)}}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n(28),i=n(6),o=n(0),s=n(1);var c=n(2);function u(t,e,n=1/0){return Object(c.a)(e)?u((n,o)=>Object(r.a)((t,r)=>e(n,t,o,r))(Object(i.c)(t(n,o))),n):("number"==typeof e&&(n=e),Object(o.b)((e,r)=>function(t,e,n,r,o,c,u,a){let l=[],d=0,f=0,h=!1;const b=()=>{!h||l.length||d||e.complete()},v=t=>d{c&&e.next(t),d++,Object(i.c)(n(t,f++)).subscribe(new s.a(e,t=>{null==o||o(t),c?v(t):e.next(t)},void 0,()=>{for(d--;l.length&&dp(t))):p(t)}b()}))};return t.subscribe(new s.a(e,v,void 0,()=>{h=!0,b()})),()=>{l=null,null==a||a()}}(e,r,t,n)))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r="function"==typeof Symbol&&Symbol.observable||"@@observable"},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(18),i=n(6);function o(t,e){return e?Object(r.a)(t,e):Object(i.b)(t)}},function(t,e,n){"use strict";n.d(e,"b",(function(){return d})),n.d(e,"a",(function(){return f}));var r=n(2),i=n(7),o=n(11),s=n(24),c=n(9);const u=a("C",void 0,void 0);function a(t,e,n){return{kind:t,value:e,error:n}}var l=n(25);class d extends i.b{constructor(t){super(),this.isStopped=!1,t?(this.destination=t,Object(i.c)(t)&&t.add(this)):this.destination=v}static create(t,e,n){return new f(t,e,n)}next(t){this.isStopped?b(function(t){return a("N",t,void 0)}(t),this):this._next(t)}error(t){this.isStopped?b(a("E",void 0,t),this):(this.isStopped=!0,this._error(t))}complete(){this.isStopped?b(u,this):(this.isStopped=!0,this._complete())}unsubscribe(){this.closed||(this.isStopped=!0,super.unsubscribe())}_next(t){this.destination.next(t)}_error(t){this.destination.error(t),this.unsubscribe()}_complete(){this.destination.complete(),this.unsubscribe()}}class f extends d{constructor(t,e,n){if(super(),this.destination=v,(t||e||n)&&t!==v){let i;if(Object(r.a)(t))i=t;else if(t){let r;({next:i,error:e,complete:n}=t),this&&o.a.useDeprecatedNextContext?(r=Object.create(t),r.unsubscribe=()=>this.unsubscribe()):r=t,i=null==i?void 0:i.bind(r),e=null==e?void 0:e.bind(r),n=null==n?void 0:n.bind(r)}this.destination={next:i||c.a,error:e||h,complete:n||c.a}}}}function h(t){if(o.a.useDeprecatedSynchronousErrorHandling)throw t;Object(s.a)(t)}function b(t,e){const{onStoppedNotification:n}=o.a;n&&l.a.setTimeout(()=>n(t,e))}const v={closed:!0,next:c.a,error:h,complete:c.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r=t=>t&&"number"==typeof t.length&&"function"!=typeof t},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(5);function i(t,e){return new r.a(n=>{let r=0;return e.schedule((function(){r===t.length?n.complete():(n.next(t[r++]),n.closed||this.schedule())}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(5);const i=new r.a(t=>t.complete())},function(t,e,n){"use strict";n.d(e,"b",(function(){return i})),n.d(e,"a",(function(){return o}));var r=n(32);const i=new(n(34).a)(r.a),o=i},function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n(5),i=n(7),o=n(23);const s=Object(o.a)(t=>function(){t(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"});var c=n(12);class u extends r.a{constructor(){super(),this.observers=[],this.closed=!1,this.isStopped=!1,this.hasError=!1,this.thrownError=null}lift(t){const e=new a(this,this);return e.operator=t,e}_throwIfClosed(){if(this.closed)throw new s}next(t){if(this._throwIfClosed(),!this.isStopped){const e=this.observers.slice();for(const n of e)n.next(t)}}error(t){if(this._throwIfClosed(),!this.isStopped){this.hasError=this.isStopped=!0,this.thrownError=t;const{observers:e}=this;for(;e.length;)e.shift().error(t)}}complete(){if(this._throwIfClosed(),!this.isStopped){this.isStopped=!0;const{observers:t}=this;for(;t.length;)t.shift().complete()}}unsubscribe(){this.isStopped=this.closed=!0,this.observers=null}_trySubscribe(t){return this._throwIfClosed(),super._trySubscribe(t)}_subscribe(t){return this._throwIfClosed(),this._checkFinalizedStatuses(t),this._innerSubscribe(t)}_innerSubscribe(t){const{hasError:e,isStopped:n,observers:r}=this;return e||n?i.a:(r.push(t),new i.b(()=>Object(c.a)(this.observers,t)))}_checkFinalizedStatuses(t){const{hasError:e,thrownError:n,isStopped:r}=this;e?t.error(n):r&&t.complete()}asObservable(){const t=new r.a;return t.source=this,t}}u.create=(t,e)=>new a(t,e);class a extends u{constructor(t,e){super(),this.destination=t,this.source=e}next(t){var e,n;null===(n=null===(e=this.destination)||void 0===e?void 0:e.next)||void 0===n||n.call(e,t)}error(t){var e,n;null===(n=null===(e=this.destination)||void 0===e?void 0:e.error)||void 0===n||n.call(e,t)}complete(){var t,e;null===(e=null===(t=this.destination)||void 0===t?void 0:t.complete)||void 0===e||e.call(t)}_subscribe(t){var e,n;return null!==(n=null===(e=this.source)||void 0===e?void 0:e.subscribe(t))&&void 0!==n?n:i.a}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(31);var i=n(15),o=n(8);function s(...t){return Object(r.a)(1)(Object(i.a)(t,Object(o.c)(t)))}},function(t,e,n){"use strict";function r(t){const e=t(t=>{Error.call(t),t.stack=(new Error).stack});return e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,e}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(11),i=n(25);function o(t){i.a.setTimeout(()=>{const{onUnhandledError:e}=r.a;if(!e)throw t;e(t)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={setTimeout(...t){const{delegate:e}=r;return((null==e?void 0:e.setTimeout)||setTimeout)(...t)},clearTimeout(t){const{delegate:e}=r;return((null==e?void 0:e.clearTimeout)||clearTimeout)(t)},delegate:void 0}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={now:()=>(r.delegate||Date).now(),delegate:void 0}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(28);const{isArray:i}=Array;function o(t){return Object(r.a)(e=>function(t,e){return i(e)?t(...e):t(e)}(t,e))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return Object(r.b)((n,r)=>{let o=0;n.subscribe(new i.a(r,n=>{r.next(t.call(e,n,o++))}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(2);function i(t){return t&&Object(r.a)(t.schedule)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));const{isArray:r}=Array;function i(t){return 1===t.length&&r(t[0])?t[0]:t}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(13),i=n(10);function o(t=1/0){return Object(r.a)(i.a,t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(7);class i extends r.b{constructor(t,e){super()}schedule(t,e=0){return this}}const o={setInterval(...t){const{delegate:e}=o;return((null==e?void 0:e.setInterval)||setInterval)(...t)},clearInterval(t){const{delegate:e}=o;return((null==e?void 0:e.clearInterval)||clearInterval)(t)},delegate:void 0};var s=n(12);class c extends i{constructor(t,e){super(t,e),this.scheduler=t,this.work=e,this.pending=!1}schedule(t,e=0){if(this.closed)return this;this.state=t;const n=this.id,r=this.scheduler;return null!=n&&(this.id=this.recycleAsyncId(r,n,e)),this.pending=!0,this.delay=e,this.id=this.id||this.requestAsyncId(r,this.id,e),this}requestAsyncId(t,e,n=0){return o.setInterval(t.flush.bind(t,this),n)}recycleAsyncId(t,e,n=0){if(null!=n&&this.delay===n&&!1===this.pending)return e;o.clearInterval(e)}execute(t,e){if(this.closed)return new Error("executing a cancelled action");this.pending=!1;const n=this._execute(t,e);if(n)return n;!1===this.pending&&null!=this.id&&(this.id=this.recycleAsyncId(this.scheduler,this.id,null))}_execute(t,e){let n,r=!1;try{this.work(t)}catch(t){r=!0,n=!!t&&t||new Error(t)}if(r)return this.unsubscribe(),n}unsubscribe(){if(!this.closed){const{id:t,scheduler:e}=this,{actions:n}=e;this.work=this.state=this.scheduler=null,this.pending=!1,Object(s.a)(n,this),null!=t&&(this.id=this.recycleAsyncId(e,t,null)),this.delay=null,super.unsubscribe()}}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(5),i=n(20),o=n(29);function s(t=0,e,n=i.a){let s=-1;return null!=e&&(Object(o.a)(e)?n=e:s=e),new r.a(e=>{let r=(i=t)instanceof Date&&!isNaN(i)?+t-n.now():t;var i;r<0&&(r=0);let o=0;return n.schedule((function(){e.closed||(e.next(o++),0<=s?this.schedule(void 0,s):e.complete())}),r)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(26);class i{constructor(t,e=i.now){this.schedulerActionCtor=t,this.now=e}schedule(t,e=0,n){return new this.schedulerActionCtor(this,t).schedule(n,e)}}i.now=r.a.now;class o extends i{constructor(t,e=i.now){super(t,e),this.actions=[],this.active=!1,this.scheduled=void 0}flush(t){const{actions:e}=this;if(this.active)return void e.push(t);let n;this.active=!0;do{if(n=t.execute(t.state,t.delay))break}while(t=e.shift());if(this.active=!1,n){for(;t=e.shift();)t.unsubscribe();throw n}}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(6),i=n(0),o=n(1);function s(t,e){return Object(i.b)((n,i)=>{let s=null,c=0,u=!1;const a=()=>u&&!s&&i.complete();n.subscribe(new o.a(i,n=>{null==s||s.unsubscribe();let u=0;const l=c++;Object(r.c)(t(n,l)).subscribe(s=new o.a(i,t=>i.next(e?e(n,t,l,u++):t),void 0,()=>{s=null,a()}))},void 0,()=>{u=!0,a()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(19),i=n(0),o=n(1);function s(t){return t<=0?()=>r.a:Object(i.b)((e,n)=>{let r=0;e.subscribe(new o.a(n,e=>{++r<=t&&(n.next(e),t<=r&&n.complete())}))})}},function(t,e,n){ -/*! - * clipboard.js v2.0.6 - * https://clipboardjs.com/ - * - * Licensed MIT © Zeno Rocha - */ -var r;r=function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},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 r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},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=6)}([function(t,e){t.exports=function(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus();var r=window.getSelection(),i=document.createRange();i.selectNodeContents(t),r.removeAllRanges(),r.addRange(i),e=r.toString()}return e}},function(t,e){function n(){}n.prototype={on:function(t,e,n){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var r=this;function i(){r.off(t,i),e.apply(n,arguments)}return i._=e,this.on(t,i,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,i=n.length;r0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":o(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),t}(),u=n(1),a=n.n(u),l=n(2),d=n.n(l),f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===f(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=d()(t,"click",(function(t){return e.onClick(t)}))}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new c({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return v("action",t)}},{key:"defaultTarget",value:function(t){var e=v("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return v("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach((function(t){n=n&&!!document.queryCommandSupported(t)})),n}}]),e}(a.a);function v(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}e.default=b}]).default},t.exports=r()},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(21),i=n(26);class o extends r.a{constructor(t=1/0,e=1/0,n=i.a){super(),this.bufferSize=t,this.windowTime=e,this.timestampProvider=n,this.buffer=[],this.infiniteTimeWindow=!0,this.infiniteTimeWindow=e===1/0,this.bufferSize=Math.max(1,t),this.windowTime=Math.max(1,e)}next(t){const{isStopped:e,buffer:n,infiniteTimeWindow:r,timestampProvider:i,windowTime:o}=this;e||(n.push(t),!r&&n.push(i.now()+o)),this.trimBuffer(),super.next(t)}_subscribe(t){this._throwIfClosed(),this.trimBuffer();const e=this._innerSubscribe(t),{infiniteTimeWindow:n,buffer:r}=this,i=r.slice();for(let e=0;ee(t),e)}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t){return Object(r.b)((e,n)=>{e.subscribe(new i.a(n,()=>n.next(t)))})}},function(t,e,n){"use strict";(function(t){var n=function(){if("undefined"!=typeof Map)return Map;function t(t,e){var n=-1;return t.some((function(t,r){return t[0]===e&&(n=r,!0)})),n}return function(){function e(){this.__entries__=[]}return Object.defineProperty(e.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),e.prototype.get=function(e){var n=t(this.__entries__,e),r=this.__entries__[n];return r&&r[1]},e.prototype.set=function(e,n){var r=t(this.__entries__,e);~r?this.__entries__[r][1]=n:this.__entries__.push([e,n])},e.prototype.delete=function(e){var n=this.__entries__,r=t(n,e);~r&&n.splice(r,1)},e.prototype.has=function(e){return!!~t(this.__entries__,e)},e.prototype.clear=function(){this.__entries__.splice(0)},e.prototype.forEach=function(t,e){void 0===e&&(e=null);for(var n=0,r=this.__entries__;n0},t.prototype.connect_=function(){r&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),c?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},t.prototype.disconnect_=function(){r&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},t.prototype.onTransitionEnd_=function(t){var e=t.propertyName,n=void 0===e?"":e;s.some((function(t){return!!~n.indexOf(t)}))&&this.refresh()},t.getInstance=function(){return this.instance_||(this.instance_=new t),this.instance_},t.instance_=null,t}(),a=function(t,e){for(var n=0,r=Object.keys(e);n0},t}(),_="undefined"!=typeof WeakMap?new WeakMap:new n,O=function t(e){if(!(this instanceof t))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var n=u.getInstance(),r=new g(e,n,this);_.set(this,r)};["observe","unobserve","disconnect"].forEach((function(t){O.prototype[t]=function(){var e;return(e=_.get(this))[t].apply(e,arguments)}}));var j=void 0!==i.ResizeObserver?i.ResizeObserver:O;e.a=j}).call(this,n(47))},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(5),i=n(6);function o(t){return new r.a(e=>{Object(i.c)(t()).subscribe(e)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return Object(r.b)((n,r)=>{let o=0;n.subscribe(new i.a(r,n=>t.call(e,n,o++)&&r.next(n)))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return t=null!=t?t:s,Object(r.b)((n,r)=>{let o,s=!0;n.subscribe(new i.a(r,n=>{(s&&(o=n,1)||!t(o,o=e?e(n):n))&&r.next(n),s=!1}))})}function s(t,e){return t===e}},function(t,e,n){"use strict"; -/*! - * escape-html - * Copyright(c) 2012-2013 TJ Holowaychuk - * Copyright(c) 2015 Andreas Lubbe - * Copyright(c) 2015 Tiancheng "Timothy" Gu - * MIT Licensed - */var r=/["'&<>]/;t.exports=function(t){var e,n=""+t,i=r.exec(n);if(!i)return n;var o="",s=0,c=0;for(s=i.index;si=>t[r](e,i,n)):function(t){return Object(s.a)(t.addListener)&&Object(s.a)(t.removeListener)}(t)?a.map(h(t,e)):function(t){return Object(s.a)(t.on)&&Object(s.a)(t.off)}(t)?d.map(h(t,e)):[];return!v&&Object(o.a)(t)?Object(i.a)(t=>f(t,e,n))(Object(u.a)(t)):new r.a(t=>{if(!v)throw new TypeError("Invalid event target");const e=(...e)=>t.next(1p(e)})}function h(t,e){return n=>r=>t[n](e,r)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(31),i=n(15),o=n(30),s=n(6),c=n(19),u=n(8);function a(...t){const e=Object(u.c)(t),n=Object(u.a)(t,1/0),a=Object(o.a)(t);return a.length?1===a.length?Object(s.c)(a[0]):Object(r.a)(n)(Object(i.a)(a,e)):c.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(22),i=n(8),o=n(0);function s(...t){const e=Object(i.c)(t);return Object(o.b)((n,i)=>{(e?Object(r.a)(t,n,e):Object(r.a)(t,n)).subscribe(i)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(15),i=n(18),o=n(8);function s(...t){const e=Object(o.c)(t);return e?Object(i.a)(t,e):Object(r.a)(t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(5),i=n(9);const o=new r.a(i.a)},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(0);function i(t){return Object(r.b)((e,n)=>{e.subscribe(n),n.add(t)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(38),i=n(0);function o(t,e,n){let o;return o=t&&"object"==typeof t?t:{bufferSize:t,windowTime:e,refCount:!1,scheduler:n},Object(i.b)(function({bufferSize:t=1/0,windowTime:e=1/0,refCount:n,scheduler:i}){let o,s,c=0;return(u,a)=>{let l;c++,o?l=o.subscribe(a):(o=new r.a(t,e,i),l=o.subscribe(a),s=u.subscribe({next(t){o.next(t)},error(t){const e=o;s=void 0,o=void 0,e.error(t)},complete(){s=void 0,o.complete()}}),s.closed&&(s=void 0)),a.add(()=>{c--,l.unsubscribe(),n&&0===c&&s&&(s.unsubscribe(),s=void 0,o=void 0)})}}(o))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(2),i=n(0),o=n(1),s=n(10);function c(t,e,n){const c=Object(r.a)(t)||e||n?{next:t,error:e,complete:n}:t;return c?Object(i.b)((t,e)=>{t.subscribe(new o.a(e,t=>{var n;null===(n=c.next)||void 0===n||n.call(c,t),e.next(t)},t=>{var n;null===(n=c.error)||void 0===n||n.call(c,t),e.error(t)},()=>{var t;null===(t=c.complete)||void 0===t||t.call(c),e.complete()}))}):s.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(21);class i extends r.a{constructor(t){super(),this._value=t}get value(){return this.getValue()}_subscribe(t){const e=super._subscribe(t);return!e.closed&&t.next(this._value),e}getValue(){const{hasError:t,thrownError:e,_value:n}=this;if(t)throw e;return this._throwIfClosed(),n}next(t){super.next(this._value=t)}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(44);function i(t,e){return Object(r.a)((n,r)=>e?e(n[t],r[t]):n[t]===r[t])}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(0),i=n(1),o=n(6);const s={leading:!0,trailing:!1};function c(t,{leading:e,trailing:n}=s){return Object(r.b)((r,s)=>{let c=!1,u=null,a=null,l=!1;const d=()=>{null==a||a.unsubscribe(),a=null,n&&(b(),l&&s.complete())},f=()=>{a=null,l&&s.complete()},h=e=>a=Object(o.c)(t(e)).subscribe(new i.a(s,d,void 0,f)),b=()=>{c&&(s.next(u),!l&&h(u)),c=!1,u=null};r.subscribe(new i.a(s,t=>{c=!0,u=t,(!a||a.closed)&&(e?b():h(t))},void 0,()=>{l=!0,(!(n&&c&&a)||a.closed)&&s.complete()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(35);function i(t,e){return e?Object(r.a)(()=>t,e):Object(r.a)(()=>t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e=0){return Object(r.b)((n,r)=>{n.subscribe(new i.a(r,n=>r.add(t.schedule(()=>r.next(n),e)),n=>r.add(t.schedule(()=>r.error(n),e)),()=>r.add(t.schedule(()=>r.complete(),e))))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(0),i=n(1),o=n(6),s=n(10),c=n(9),u=n(8);function a(...t){const e=Object(u.b)(t);return Object(r.b)((n,r)=>{const u=t.length,a=new Array(u);let l=t.map(()=>!1),d=!1;for(let e=0;e{a[e]=t,d||l[e]||(l[e]=!0,(d=l.every(s.a))&&(l=null))},void 0,c.a));n.subscribe(new i.a(r,t=>{if(d){const n=[t,...a];r.next(e?e(...n):n)}}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(0),i=n(9),o=n(1);function s(t){return Object(r.b)((e,n)=>{let r=!1,s=null;e.subscribe(new o.a(n,t=>{r=!0,s=t}));t.subscribe(new o.a(n,()=>{if(r){r=!1;const t=s;s=null,n.next(t)}},void 0,i.a))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(43);function i(t){return Object(r.a)((e,n)=>t<=n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(6),i=n(1),o=n(0);function s(t){return Object(o.b)((e,n)=>{let o,c=null,u=!1;c=e.subscribe(new i.a(n,void 0,i=>{o=Object(r.c)(t(i,s(t)(e))),c?(c.unsubscribe(),c=null,o.subscribe(n)):u=!0})),u&&(c.unsubscribe(),c=null,o.subscribe(n))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(0),i=n(1),o=n(12);function s(t,e=null){return e=null!=e?e:t,Object(r.b)((n,r)=>{let s=[],c=0;n.subscribe(new i.a(r,n=>{let i=null;c++%e==0&&s.push([]);for(const e of s)e.push(n),t<=e.length&&(i=null!=i?i:[],i.push(e));if(i)for(const t of i)Object(o.a)(s,t),r.next(t)},void 0,()=>{for(const t of s)r.next(t);r.complete()},()=>{s=null}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(13),i=n(2);function o(t,e){return Object(i.a)(e)?Object(r.a)(t,e,1):Object(r.a)(t,1)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(42);function i(t,e,n){return Object(r.a)(()=>t()?e:n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t=null){return Object(r.b)((e,n)=>{let r=!1;e.subscribe(new i.a(n,t=>{r=!0,n.next(t)},void 0,()=>{r||n.next(t),n.complete()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return f}));var r=n(5),i=n(7),o=n(0),s=n(1);function c(){return Object(o.b)((t,e)=>{let n=null;t._refCount++;const r=new s.a(e,void 0,void 0,void 0,()=>{if(!t||t._refCount<=0||0<--t._refCount)return void(n=null);const r=t._connection,i=n;n=null,!r||i&&r!==i||r.unsubscribe(),e.unsubscribe()});t.subscribe(r),r.closed||(n=t.connect())})}class u extends r.a{constructor(t,e){super(),this.source=t,this.subjectFactory=e,this._subject=null,this._refCount=0,this._connection=null}_subscribe(t){return this.getSubject().subscribe(t)}getSubject(){const t=this._subject;return t&&!t.isStopped||(this._subject=this.subjectFactory()),this._subject}_teardown(){this._refCount=0;const{_connection:t}=this;this._subject=this._connection=null,null==t||t.unsubscribe()}connect(){let t=this._connection;if(!t){t=this._connection=new i.b;const e=this.getSubject();t.add(this.source.subscribe(new s.a(e,void 0,t=>{this._teardown(),e.error(t)},()=>{this._teardown(),e.complete()},()=>this._teardown()))),t.closed&&(this._connection=null,t=i.b.EMPTY)}return t}refCount(){return c()(this)}}var a=n(2);var l=n(21);function d(){return new l.a}function f(){return t=>c()(function(t,e){const n=Object(a.a)(t)?t:()=>t;return Object(a.a)(e)?Object(o.b)((t,r)=>{const i=n();e(i).subscribe(r).add(t.subscribe(i))}):t=>{const e=new u(t,n);return Object(o.a)(t)&&(e.lift=t.lift),e.source=t,e.subjectFactory=n,e}}(d)(t))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(32),i=n(7);const o={schedule(t){let e=requestAnimationFrame,n=cancelAnimationFrame;const{delegate:r}=o;r&&(e=r.requestAnimationFrame,n=r.cancelAnimationFrame);const s=e(e=>{n=void 0,t(e)});return new i.b(()=>null==n?void 0:n(s))},requestAnimationFrame(...t){const{delegate:e}=o;return((null==e?void 0:e.requestAnimationFrame)||requestAnimationFrame)(...t)},cancelAnimationFrame(...t){const{delegate:e}=o;return((null==e?void 0:e.cancelAnimationFrame)||cancelAnimationFrame)(...t)},delegate:void 0};class s extends r.a{constructor(t,e){super(t,e),this.scheduler=t,this.work=e}requestAsyncId(t,e,n=0){return null!==n&&n>0?super.requestAsyncId(t,e,n):(t.actions.push(this),t.scheduled||(t.scheduled=o.requestAnimationFrame(()=>t.flush(void 0))))}recycleAsyncId(t,e,n=0){if(null!=n&&n>0||null==n&&this.delay>0)return super.recycleAsyncId(t,e,n);0===t.actions.length&&(o.cancelAnimationFrame(e),t.scheduled=void 0)}}var c=n(34);class u extends c.a{flush(t){this.active=!0,this.scheduled=void 0;const{actions:e}=this;let n,r=-1;t=t||e.shift();const i=e.length;do{if(n=t.execute(t.state,t.delay))break}while(++rObject(i.a)(e.pipe(Object(o.a)(1),Object(s.b)((t,e)=>{t.subscribe(new c.a(e,u.a))})),n.pipe(d(t))):Object(l.a)((e,n)=>t(e,n).pipe(Object(o.a)(1),Object(a.a)(e)))}var f=n(33);function h(t,e=r.b){const n=Object(f.a)(t,e);return d(()=>n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return b}));var r=n(5);const{isArray:i}=Array,{getPrototypeOf:o,prototype:s,keys:c}=Object;function u(t){if(1===t.length){const n=t[0];if(i(n))return{args:n,keys:null};if((e=n)&&"object"==typeof e&&o(e)===s){const t=c(n);return{args:t.map(t=>n[t]),keys:t}}}var e;return{args:t,keys:null}}var a=n(16),l=n(6),d=n(10),f=n(27),h=n(8);function b(...t){const e=Object(h.c)(t),n=Object(h.b)(t),{args:i,keys:o}=u(t),s=new r.a(function(t,e,n=d.a){return r=>{p(e,()=>{const{length:i}=t,o=new Array(i);let s=i;const c=t.map(()=>!1);let u=!0;for(let a=0;a{Object(l.a)(t[a],e).subscribe(new v(r,t=>{o[a]=t,u&&(c[a]=!0,u=!c.every(d.a)),u||r.next(n(o.slice()))},()=>0==--s))},r)}},r)}}(i,e,o?t=>{const e={};for(let n=0;n{let u=n,a=e,l=0;s.subscribe(new i.a(c,e=>{const n=l++;a=u?t(a,e,n):(u=!0,e),r&&c.next(a)},void 0,o&&(()=>{u&&c.next(a),c.complete()})))}}function s(t,e){return Object(r.b)(o(t,e,arguments.length>=2,!0))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return d}));var r=n(5),i=n(6),o=n(30),s=n(19),c=n(1),u=n(8);var a=n(0);function l(...t){return Object(a.b)((e,n)=>{(function(...t){const e=Object(u.b)(t),n=Object(o.a)(t);return n.length?new r.a(t=>{let r=n.map(()=>[]),o=n.map(()=>!1);t.add(()=>{r=o=null});for(let s=0;!t.closed&&s{if(r[s].push(n),r.every(t=>t.length)){const n=r.map(t=>t.shift());t.next(e?e(...n):n),r.some((t,e)=>!t.length&&o[e])&&t.complete()}},void 0,()=>{o[s]=!0,!r[s].length&&t.complete()}));return()=>{r=o=null}}):s.a})(e,...t).subscribe(n)})}function d(...t){return l(...t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(20),i=n(0),o=n(9),s=n(1),c=n(6);var u=n(33);function a(t,e=r.b){const n=Object(u.a)(t,e);return a=()=>n,Object(i.b)((t,e)=>{let n=!1,r=null,i=null;const u=()=>{if(null==i||i.unsubscribe(),i=null,n){n=!1;const t=r;r=null,e.next(t)}};t.subscribe(new s.a(e,t=>{null==i||i.unsubscribe(),n=!0,r=t,i=new s.a(e,u,void 0,o.a),Object(c.c)(a(t)).subscribe(i)},void 0,()=>{u(),e.complete()},()=>{r=i=null}))});var a}}]]); -//# sourceMappingURL=vendor.08c56446.min.js.map \ No newline at end of file diff --git a/docs/assets/javascripts/vendor.08c56446.min.js.map b/docs/assets/javascripts/vendor.08c56446.min.js.map deleted file mode 100644 index b8fc684..0000000 --- a/docs/assets/javascripts/vendor.08c56446.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./node_modules/rxjs/dist/esm/internal/util/lift.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/OperatorSubscriber.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isFunction.js","webpack:///./node_modules/rxjs/dist/esm/internal/Observable.js","webpack:///./node_modules/tslib/tslib.es6.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isPromise.js","webpack:///./node_modules/rxjs/dist/esm/internal/symbol/iterator.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isInteropObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isAsyncIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/throwUnobservableError.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduled.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/schedulePromise.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleAsyncIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/caughtSchedule.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/from.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/UnsubscriptionError.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subscription.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/args.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/noop.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/identity.js","webpack:///./node_modules/rxjs/dist/esm/internal/config.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/arrRemove.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeInternals.js","webpack:///./node_modules/rxjs/dist/esm/internal/symbol/observable.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/fromArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/NotificationFactories.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subscriber.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isArrayLike.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/empty.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/async.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/ObjectUnsubscribedError.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subject.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/concat.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/concatAll.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/createErrorClass.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/reportUnhandledError.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/timeoutProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/dateTimestampProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/mapOneOrManyArgs.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/map.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/argsOrArgArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeAll.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/Action.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/intervalProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AsyncAction.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/timer.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isDate.js","webpack:///./node_modules/rxjs/dist/esm/internal/Scheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AsyncScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/switchMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/take.js","webpack:///./node_modules/clipboard/dist/clipboard.js","webpack:///./node_modules/rxjs/dist/esm/internal/ReplaySubject.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/pipe.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mapTo.js","webpack:///./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/defer.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/filter.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/distinctUntilChanged.js","webpack:///./node_modules/escape-html/index.js","webpack:///./node_modules/focus-visible/dist/focus-visible.js","webpack:///(webpack)/buildin/global.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/fromEvent.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/merge.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/startWith.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/of.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/never.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/finalize.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/shareReplay.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/tap.js","webpack:///./node_modules/rxjs/dist/esm/internal/BehaviorSubject.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/distinctUntilKeyChanged.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/throttle.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/switchMapTo.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/observeOn.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/withLatestFrom.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/sample.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/skip.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/catchError.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/bufferCount.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/concatMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/iif.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/defaultIfEmpty.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/refCount.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/ConnectableObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/share.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/multicast.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/animationFrameProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameAction.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/animationFrame.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/delayWhen.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/ignoreElements.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/delay.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/argsArgArrayOrObject.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/combineLatest.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/scanInternals.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/scan.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/zipWith.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/zip.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/debounceTime.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/debounce.js"],"names":["hasLift","source","lift","operate","init","liftedSource","this","err","error","TypeError","OperatorSubscriber","destination","onNext","onError","onComplete","onUnsubscribe","super","_next","value","_error","unsubscribe","_complete","_a","closed","call","isFunction","Observable","subscribe","_subscribe","operator","observable","observerOrNext","complete","subscriber","next","isObserver","add","useDeprecatedSynchronousErrorHandling","_trySubscribe","sink","promiseCtor","getPromiseCtor","resolve","reject","subscription","operations","length","x","Promise","create","__awaiter","thisArg","_arguments","P","generator","fulfilled","step","e","rejected","result","done","then","apply","Object","__values","o","s","Symbol","iterator","m","i","__asyncValues","asyncIterator","verb","n","v","d","settle","isPromise","isInteropObservable","input","isIterable","isAsyncIterable","obj","createInvalidObservableTypeError","scheduled","scheduler","sub","Subscription","schedule","scheduleObservable","isArrayLike","scheduleArray","schedulePromise","Error","scheduleAsyncIterable","execute","delay","caughtSchedule","return","scheduleIterable","from","innerFrom","obs","fromArrayLike","promise","reportUnhandledError","asyncIterable","asyncIterable_1","asyncIterable_1_1","e_1","e_1_1","process","catch","iterable","array","UnsubscriptionError","createErrorClass","_super","errors","message","map","toString","join","name","initialTeardown","_parentage","_teardowns","Array","isArray","parent","remove","teardown","execTeardown","push","_hasParent","_addParent","includes","arrRemove","_removeParent","EMPTY","empty","EMPTY_SUBSCRIPTION","isSubscription","last","arr","popResultSelector","args","pop","undefined","popScheduler","popNumber","defaultValue","noop","identity","config","onUnhandledError","onStoppedNotification","useDeprecatedNextContext","item","index","indexOf","splice","mergeMap","project","resultSelector","concurrent","Infinity","a","b","ii","onBeforeNext","expand","innerSubScheduler","additionalTeardown","buffer","active","isComplete","checkComplete","outerNext","doInnerSub","innerValue","bufferedValue","shift","mergeInternals","internalFromArray","COMPLETE_NOTIFICATION","createNotification","kind","isStopped","EMPTY_OBSERVER","handleStoppedNotification","nextNotification","context","bind","defaultErrorHandler","notification","timeoutProvider","setTimeout","asyncScheduler","async","ObjectUnsubscribedError","observers","hasError","thrownError","subject","_throwIfClosed","copy","slice","observer","_checkFinalizedStatuses","_innerSubscribe","_b","concat","mergeAll","concatAll","createImpl","ctorFunc","instance","stack","prototype","constructor","delegate","handle","clearTimeout","dateTimestampProvider","now","Date","mapOneOrManyArgs","fn","callOrApply","isScheduler","argsOrArgArray","work","state","intervalProvider","setInterval","clearInterval","pending","id","recycleAsyncId","requestAsyncId","_id","flush","_scheduler","_execute","_delay","errorValue","errored","actions","timer","dueTime","intervalOrScheduler","intervalDuration","due","isNaN","Scheduler","schedulerActionCtor","SchedulerAction","action","switchMap","innerSubscriber","innerIndex","outerIndex","take","count","seen","factory","modules","installedModules","__webpack_require__","moduleId","exports","module","l","c","getter","defineProperty","enumerable","get","r","toStringTag","t","mode","__esModule","ns","key","object","property","hasOwnProperty","p","element","selectedText","nodeName","focus","isReadOnly","hasAttribute","setAttribute","select","setSelectionRange","removeAttribute","selection","window","getSelection","range","document","createRange","selectNodeContents","removeAllRanges","addRange","E","on","callback","ctx","once","self","listener","off","arguments","_","emit","data","evtArr","len","evts","liveEvents","TinyEmitter","is","target","type","string","node","addEventListener","destroy","removeEventListener","listenNode","nodeList","forEach","listenNodeList","selector","body","listenSelector","HTMLElement","nodeType","String","closest","_delegate","useCapture","listenerFn","delegateTarget","elements","querySelectorAll","Element","matches","proto","matchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","webkitMatchesSelector","parentNode","__webpack_exports__","src_select","select_default","_typeof","_createClass","defineProperties","props","descriptor","configurable","writable","Constructor","protoProps","staticProps","clipboard_action","ClipboardAction","options","_classCallCheck","resolveOptions","initSelection","container","emitter","text","trigger","selectFake","selectTarget","_this","isRTL","documentElement","getAttribute","removeFake","fakeHandlerCallback","fakeHandler","fakeElem","createElement","style","fontSize","border","padding","margin","position","yPosition","pageYOffset","scrollTop","top","appendChild","copyText","removeChild","succeeded","execCommand","handleResult","clearSelection","activeElement","blur","set","_action","_target","tiny_emitter","tiny_emitter_default","listen","listen_default","clipboard_typeof","clipboard_createClass","clipboard_Clipboard","_Emitter","Clipboard","clipboard_classCallCheck","ReferenceError","_possibleConstructorReturn","__proto__","getPrototypeOf","listenClick","subClass","superClass","setPrototypeOf","_inherits","defaultAction","defaultTarget","defaultText","_this2","onClick","currentTarget","clipboardAction","getAttributeValue","querySelector","support","queryCommandSupported","suffix","attribute","ReplaySubject","bufferSize","windowTime","timestampProvider","infiniteTimeWindow","Math","max","trimBuffer","adjustedBufferSize","pipe","fns","pipeFromArray","reduce","prev","mapTo","MapShim","Map","getIndex","some","entry","class_1","__entries__","delete","entries","has","clear","_i","isBrowser","global$1","global","Function","requestAnimationFrame$1","requestAnimationFrame","transitionKeys","mutationObserverSupported","MutationObserver","ResizeObserverController","connected_","mutationEventsAdded_","mutationsObserver_","observers_","onTransitionEnd_","refresh","leadingCall","trailingCall","lastCallTime","resolvePending","proxy","timeoutCallback","timeStamp","throttle","addObserver","connect_","removeObserver","disconnect_","updateObservers_","activeObservers","filter","gatherActive","hasActive","broadcastActive","observe","attributes","childList","characterData","subtree","disconnect","propertyName","getInstance","instance_","defineConfigurable","keys","getWindowOf","ownerDocument","defaultView","emptyRect","createRectInit","toFloat","parseFloat","getBordersSize","styles","positions","size","getHTMLElementContentRect","clientWidth","clientHeight","getComputedStyle","paddings","positions_1","getPaddings","horizPad","left","right","vertPad","bottom","width","height","boxSizing","round","isDocumentElement","vertScrollbar","horizScrollbar","abs","isSVGGraphicsElement","SVGGraphicsElement","SVGElement","getBBox","getContentRect","bbox","getSVGContentRect","y","ResizeObservation","broadcastWidth","broadcastHeight","contentRect_","isActive","rect","broadcastRect","ResizeObserverEntry","rectInit","Constr","contentRect","DOMRectReadOnly","ResizeObserverSPI","controller","callbackCtx","activeObservations_","observations_","callback_","controller_","callbackCtx_","observations","unobserve","clearActive","observation","WeakMap","ResizeObserver","method","defer","observableFactory","predicate","distinctUntilChanged","compare","keySelector","defaultCompare","first","matchHtmlRegExp","escape","str","match","exec","html","lastIndex","charCodeAt","substring","applyFocusVisiblePolyfill","scope","hadKeyboardEvent","hadFocusVisibleRecently","hadFocusVisibleRecentlyTimeout","inputTypesAllowlist","search","url","tel","email","password","number","date","month","week","time","datetime","isValidFocusTarget","el","classList","addFocusVisibleClass","contains","onPointerDown","addInitialPointerMoveListeners","onInitialPointerMove","toLowerCase","metaKey","altKey","ctrlKey","visibilityState","tagName","readOnly","isContentEditable","Node","DOCUMENT_FRAGMENT_NODE","host","DOCUMENT_NODE","event","CustomEvent","createEvent","initCustomEvent","dispatchEvent","g","nodeEventEmitterMethods","eventTargetMethods","jqueryMethods","fromEvent","eventName","isEventTarget","methodName","handler","addListener","removeListener","isNodeStyleEventEmitter","toCommonHandlerRegistry","isJQueryStyleEventEmitter","subTarget","merge","sources","startWith","values","of","NEVER","finalize","shareReplay","configOrBufferSize","refCount","useRefCount","innerSub","dest","shareReplayOperator","tap","tapObserver","BehaviorSubject","_value","getValue","distinctUntilKeyChanged","defaultThrottleConfig","leading","trailing","durationSelector","hasValue","sendValue","throttled","endThrottling","send","cleanupThrottling","startThrottle","switchMapTo","innerObservable","observeOn","withLatestFrom","inputs","otherValues","ready","every","sample","notifier","lastValue","skip","catchError","handledResult","syncUnsub","bufferCount","startBufferEvery","buffers","toEmit","concatMap","iif","condition","trueResult","falseResult","defaultIfEmpty","connection","_refCount","refCounter","sharedConnection","_connection","conn","connect","subjectFactory","_subject","getSubject","_teardown","shareSubjectFactory","Subject","share","subjectOrSubjectFactory","connectable","multicast","animationFrameProvider","request","cancel","cancelAnimationFrame","timestamp","AsyncAction","AsyncScheduler","animationFrameScheduler","delayWhen","delayDurationSelector","subscriptionDelay","duration","objectProto","getKeys","argsArgArrayOrObject","combineLatest","observables","valueTransform","maybeSchedule","hasValues","waitingForFirstValues","combineLatestInit","Subscriber","shouldComplete","scanInternals","accumulator","seed","hasSeed","emitOnNext","emitBeforeComplete","hasState","scan","completed","sourceIndex","zip","zipWith","otherInputs","debounceTime","durationSubscriber"],"mappings":"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","file":"assets/javascripts/vendor.08c56446.min.js","sourcesContent":["import { isFunction } from './isFunction';\nexport function hasLift(source) {\n return isFunction(source === null || source === void 0 ? void 0 : source.lift);\n}\nexport function operate(init) {\n return (source) => {\n if (hasLift(source)) {\n return source.lift(function (liftedSource) {\n try {\n return init(liftedSource, this);\n }\n catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n//# sourceMappingURL=lift.js.map","import { Subscriber } from '../Subscriber';\nexport class OperatorSubscriber extends Subscriber {\n constructor(destination, onNext, onError, onComplete, onUnsubscribe) {\n super(destination);\n this.onUnsubscribe = onUnsubscribe;\n if (onNext) {\n this._next = function (value) {\n try {\n onNext(value);\n }\n catch (err) {\n this.destination.error(err);\n }\n };\n }\n if (onError) {\n this._error = function (err) {\n try {\n onError(err);\n }\n catch (err) {\n this.destination.error(err);\n }\n this.unsubscribe();\n };\n }\n if (onComplete) {\n this._complete = function () {\n try {\n onComplete();\n }\n catch (err) {\n this.destination.error(err);\n }\n this.unsubscribe();\n };\n }\n }\n unsubscribe() {\n var _a;\n !this.closed && ((_a = this.onUnsubscribe) === null || _a === void 0 ? void 0 : _a.call(this));\n super.unsubscribe();\n }\n}\n//# sourceMappingURL=OperatorSubscriber.js.map","export function isFunction(value) {\n return typeof value === 'function';\n}\n//# sourceMappingURL=isFunction.js.map","import { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription } from './Subscription';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nexport class Observable {\n constructor(subscribe) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n lift(operator) {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n subscribe(observerOrNext, error, complete) {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n const { operator, source } = this;\n subscriber.add(operator\n ? operator.call(subscriber, source)\n : source || config.useDeprecatedSynchronousErrorHandling\n ? this._subscribe(subscriber)\n : this._trySubscribe(subscriber));\n return subscriber;\n }\n _trySubscribe(sink) {\n try {\n return this._subscribe(sink);\n }\n catch (err) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n throw err;\n }\n sink.error(err);\n }\n }\n forEach(next, promiseCtor) {\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor((resolve, reject) => {\n let subscription;\n subscription = this.subscribe((value) => {\n try {\n next(value);\n }\n catch (err) {\n reject(err);\n subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe();\n }\n }, reject, resolve);\n });\n }\n _subscribe(subscriber) {\n var _a;\n return (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber);\n }\n [Symbol_observable]() {\n return this;\n }\n pipe(...operations) {\n return operations.length ? pipeFromArray(operations)(this) : this;\n }\n toPromise(promiseCtor) {\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor((resolve, reject) => {\n let value;\n this.subscribe((x) => (value = x), (err) => reject(err), () => resolve(value));\n });\n }\n}\nObservable.create = (subscribe) => {\n return new Observable(subscribe);\n};\nfunction getPromiseCtor(promiseCtor) {\n var _a;\n return (_a = promiseCtor !== null && promiseCtor !== void 0 ? promiseCtor : config.Promise) !== null && _a !== void 0 ? _a : Promise;\n}\nfunction isObserver(value) {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\nfunction isSubscriber(value) {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n//# sourceMappingURL=Observable.js.map","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","import { isFunction } from \"./isFunction\";\nexport function isPromise(value) {\n return isFunction(value === null || value === void 0 ? void 0 : value.then);\n}\n//# sourceMappingURL=isPromise.js.map","export function getSymbolIterator() {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator';\n }\n return Symbol.iterator;\n}\nexport const iterator = getSymbolIterator();\nexport const $$iterator = iterator;\n//# sourceMappingURL=iterator.js.map","import { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\nexport function isInteropObservable(input) {\n return isFunction(input[Symbol_observable]);\n}\n//# sourceMappingURL=isInteropObservable.js.map","import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\nexport function isIterable(input) {\n return isFunction(input === null || input === void 0 ? void 0 : input[Symbol_iterator]);\n}\n//# sourceMappingURL=isIterable.js.map","import { isFunction } from './isFunction';\nexport function isAsyncIterable(obj) {\n return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);\n}\n//# sourceMappingURL=isAsyncIterable.js.map","export function createInvalidObservableTypeError(input) {\n return new TypeError(`You provided ${input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`} where a stream was expected. You can provide an Observable, Promise, Array, AsyncIterable, or Iterable.`);\n}\n//# sourceMappingURL=throwUnobservableError.js.map","import { scheduleObservable } from './scheduleObservable';\nimport { schedulePromise } from './schedulePromise';\nimport { scheduleArray } from './scheduleArray';\nimport { scheduleIterable } from './scheduleIterable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isPromise } from '../util/isPromise';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isIterable } from '../util/isIterable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nexport function scheduled(input, scheduler) {\n if (input != null) {\n if (isInteropObservable(input)) {\n return scheduleObservable(input, scheduler);\n }\n if (isArrayLike(input)) {\n return scheduleArray(input, scheduler);\n }\n if (isPromise(input)) {\n return schedulePromise(input, scheduler);\n }\n if (isAsyncIterable(input)) {\n return scheduleAsyncIterable(input, scheduler);\n }\n if (isIterable(input)) {\n return scheduleIterable(input, scheduler);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\n//# sourceMappingURL=scheduled.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nimport { observable as Symbol_observable } from '../symbol/observable';\nexport function scheduleObservable(input, scheduler) {\n return new Observable(subscriber => {\n const sub = new Subscription();\n sub.add(scheduler.schedule(() => {\n const observable = input[Symbol_observable]();\n sub.add(observable.subscribe({\n next(value) { sub.add(scheduler.schedule(() => subscriber.next(value))); },\n error(err) { sub.add(scheduler.schedule(() => subscriber.error(err))); },\n complete() { sub.add(scheduler.schedule(() => subscriber.complete())); },\n }));\n }));\n return sub;\n });\n}\n//# sourceMappingURL=scheduleObservable.js.map","import { Observable } from '../Observable';\nexport function schedulePromise(input, scheduler) {\n return new Observable((subscriber) => {\n return scheduler.schedule(() => input.then((value) => {\n subscriber.add(scheduler.schedule(() => {\n subscriber.next(value);\n subscriber.add(scheduler.schedule(() => subscriber.complete()));\n }));\n }, (err) => {\n subscriber.add(scheduler.schedule(() => subscriber.error(err)));\n }));\n });\n}\n//# sourceMappingURL=schedulePromise.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nexport function scheduleAsyncIterable(input, scheduler) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n return new Observable(subscriber => {\n const sub = new Subscription();\n sub.add(scheduler.schedule(() => {\n const iterator = input[Symbol.asyncIterator]();\n sub.add(scheduler.schedule(function () {\n iterator.next().then(result => {\n if (result.done) {\n subscriber.complete();\n }\n else {\n subscriber.next(result.value);\n this.schedule();\n }\n });\n }));\n }));\n return sub;\n });\n}\n//# sourceMappingURL=scheduleAsyncIterable.js.map","import { Observable } from '../Observable';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from '../util/isFunction';\nimport { caughtSchedule } from '../util/caughtSchedule';\nexport function scheduleIterable(input, scheduler) {\n return new Observable((subscriber) => {\n let iterator;\n subscriber.add(scheduler.schedule(() => {\n iterator = input[Symbol_iterator]();\n caughtSchedule(subscriber, scheduler, function () {\n const { value, done } = iterator.next();\n if (done) {\n subscriber.complete();\n }\n else {\n subscriber.next(value);\n this.schedule();\n }\n });\n }));\n return () => isFunction(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return();\n });\n}\n//# sourceMappingURL=scheduleIterable.js.map","export function caughtSchedule(subscriber, scheduler, execute, delay = 0) {\n const subscription = scheduler.schedule(function () {\n try {\n execute.call(this);\n }\n catch (err) {\n subscriber.error(err);\n }\n }, delay);\n subscriber.add(subscription);\n return subscription;\n}\n//# sourceMappingURL=caughtSchedule.js.map","import { __asyncValues, __awaiter } from \"tslib\";\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isPromise } from '../util/isPromise';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { Observable } from '../Observable';\nimport { scheduled } from '../scheduled/scheduled';\nimport { isFunction } from '../util/isFunction';\nimport { reportUnhandledError } from '../util/reportUnhandledError';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isIterable } from '../util/isIterable';\nexport function from(input, scheduler) {\n return scheduler ? scheduled(input, scheduler) : innerFrom(input);\n}\nexport function innerFrom(input) {\n if (input instanceof Observable) {\n return input;\n }\n if (input != null) {\n if (isInteropObservable(input)) {\n return fromInteropObservable(input);\n }\n if (isArrayLike(input)) {\n return fromArrayLike(input);\n }\n if (isPromise(input)) {\n return fromPromise(input);\n }\n if (isAsyncIterable(input)) {\n return fromAsyncIterable(input);\n }\n if (isIterable(input)) {\n return fromIterable(input);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\nfunction fromInteropObservable(obj) {\n return new Observable((subscriber) => {\n const obs = obj[Symbol_observable]();\n if (isFunction(obs.subscribe)) {\n return obs.subscribe(subscriber);\n }\n throw new TypeError('Provided object does not correctly implement Symbol.observable');\n });\n}\nexport function fromArrayLike(array) {\n return new Observable((subscriber) => {\n for (let i = 0; i < array.length && !subscriber.closed; i++) {\n subscriber.next(array[i]);\n }\n subscriber.complete();\n });\n}\nfunction fromPromise(promise) {\n return new Observable((subscriber) => {\n promise\n .then((value) => {\n if (!subscriber.closed) {\n subscriber.next(value);\n subscriber.complete();\n }\n }, (err) => subscriber.error(err))\n .then(null, reportUnhandledError);\n });\n}\nfunction fromIterable(iterable) {\n return new Observable((subscriber) => {\n const iterator = iterable[Symbol_iterator]();\n while (!subscriber.closed) {\n const { done, value } = iterator.next();\n if (done) {\n subscriber.complete();\n }\n else {\n subscriber.next(value);\n }\n }\n return () => isFunction(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return();\n });\n}\nfunction fromAsyncIterable(asyncIterable) {\n return new Observable((subscriber) => {\n process(asyncIterable, subscriber).catch((err) => subscriber.error(err));\n });\n}\nfunction process(asyncIterable, subscriber) {\n var asyncIterable_1, asyncIterable_1_1;\n var e_1, _a;\n return __awaiter(this, void 0, void 0, function* () {\n try {\n for (asyncIterable_1 = __asyncValues(asyncIterable); asyncIterable_1_1 = yield asyncIterable_1.next(), !asyncIterable_1_1.done;) {\n const value = asyncIterable_1_1.value;\n subscriber.next(value);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (asyncIterable_1_1 && !asyncIterable_1_1.done && (_a = asyncIterable_1.return)) yield _a.call(asyncIterable_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n subscriber.complete();\n });\n}\n//# sourceMappingURL=from.js.map","import { createErrorClass } from './createErrorClass';\nexport const UnsubscriptionError = createErrorClass((_super) => function UnsubscriptionErrorImpl(errors) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n});\n//# sourceMappingURL=UnsubscriptionError.js.map","import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { arrRemove } from './util/arrRemove';\nexport class Subscription {\n constructor(initialTeardown) {\n this.initialTeardown = initialTeardown;\n this.closed = false;\n this._parentage = null;\n this._teardowns = null;\n }\n unsubscribe() {\n let errors;\n if (!this.closed) {\n this.closed = true;\n const { _parentage } = this;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n }\n else {\n _parentage === null || _parentage === void 0 ? void 0 : _parentage.remove(this);\n }\n const { initialTeardown } = this;\n if (isFunction(initialTeardown)) {\n try {\n initialTeardown();\n }\n catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n const { _teardowns } = this;\n if (_teardowns) {\n this._teardowns = null;\n for (const teardown of _teardowns) {\n try {\n execTeardown(teardown);\n }\n catch (err) {\n errors = errors !== null && errors !== void 0 ? errors : [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n }\n else {\n errors.push(err);\n }\n }\n }\n }\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n add(teardown) {\n var _a;\n if (teardown && teardown !== this) {\n if (this.closed) {\n execTeardown(teardown);\n }\n else {\n if (teardown instanceof Subscription) {\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._teardowns = (_a = this._teardowns) !== null && _a !== void 0 ? _a : []).push(teardown);\n }\n }\n }\n _hasParent(parent) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n _addParent(parent) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n _removeParent(parent) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n }\n else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n remove(teardown) {\n const { _teardowns } = this;\n _teardowns && arrRemove(_teardowns, teardown);\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\nSubscription.EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n})();\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\nexport function isSubscription(value) {\n return (value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe)));\n}\nfunction execTeardown(teardown) {\n if (isFunction(teardown)) {\n teardown();\n }\n else {\n teardown.unsubscribe();\n }\n}\n//# sourceMappingURL=Subscription.js.map","import { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\nfunction last(arr) {\n return arr[arr.length - 1];\n}\nexport function popResultSelector(args) {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\nexport function popScheduler(args) {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\nexport function popNumber(args, defaultValue) {\n return typeof last(args) === 'number' ? args.pop() : defaultValue;\n}\n//# sourceMappingURL=args.js.map","export function noop() { }\n//# sourceMappingURL=noop.js.map","export function identity(x) {\n return x;\n}\n//# sourceMappingURL=identity.js.map","export const config = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n//# sourceMappingURL=config.js.map","export function arrRemove(arr, item) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n//# sourceMappingURL=arrRemove.js.map","import { map } from './map';\nimport { innerFrom } from '../observable/from';\nimport { operate } from '../util/lift';\nimport { mergeInternals } from './mergeInternals';\nimport { isFunction } from '../util/isFunction';\nexport function mergeMap(project, resultSelector, concurrent = Infinity) {\n if (isFunction(resultSelector)) {\n return mergeMap((a, i) => map((b, ii) => resultSelector(a, b, i, ii))(innerFrom(project(a, i))), concurrent);\n }\n else if (typeof resultSelector === 'number') {\n concurrent = resultSelector;\n }\n return operate((source, subscriber) => mergeInternals(source, subscriber, project, concurrent));\n}\nexport const flatMap = mergeMap;\n//# sourceMappingURL=mergeMap.js.map","import { innerFrom } from '../observable/from';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalTeardown) {\n let buffer = [];\n let active = 0;\n let index = 0;\n let isComplete = false;\n const checkComplete = () => {\n if (isComplete && !buffer.length && !active) {\n subscriber.complete();\n }\n };\n const outerNext = (value) => (active < concurrent ? doInnerSub(value) : buffer.push(value));\n const doInnerSub = (value) => {\n expand && subscriber.next(value);\n active++;\n innerFrom(project(value, index++)).subscribe(new OperatorSubscriber(subscriber, (innerValue) => {\n onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);\n if (expand) {\n outerNext(innerValue);\n }\n else {\n subscriber.next(innerValue);\n }\n }, undefined, () => {\n active--;\n while (buffer.length && active < concurrent) {\n const bufferedValue = buffer.shift();\n innerSubScheduler ? subscriber.add(innerSubScheduler.schedule(() => doInnerSub(bufferedValue))) : doInnerSub(bufferedValue);\n }\n checkComplete();\n }));\n };\n source.subscribe(new OperatorSubscriber(subscriber, outerNext, undefined, () => {\n isComplete = true;\n checkComplete();\n }));\n return () => {\n buffer = null;\n additionalTeardown === null || additionalTeardown === void 0 ? void 0 : additionalTeardown();\n };\n}\n//# sourceMappingURL=mergeInternals.js.map","export const observable = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n//# sourceMappingURL=observable.js.map","import { scheduleArray } from '../scheduled/scheduleArray';\nimport { fromArrayLike } from './from';\nexport function internalFromArray(input, scheduler) {\n return scheduler ? scheduleArray(input, scheduler) : fromArrayLike(input);\n}\n//# sourceMappingURL=fromArray.js.map","export const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined))();\nexport function errorNotification(error) {\n return createNotification('E', undefined, error);\n}\nexport function nextNotification(value) {\n return createNotification('N', value, undefined);\n}\nexport function createNotification(kind, value, error) {\n return {\n kind,\n value,\n error,\n };\n}\n//# sourceMappingURL=NotificationFactories.js.map","import { isFunction } from './util/isFunction';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nexport class Subscriber extends Subscription {\n constructor(destination) {\n super();\n this.isStopped = false;\n if (destination) {\n this.destination = destination;\n if (isSubscription(destination)) {\n destination.add(this);\n }\n }\n else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n static create(next, error, complete) {\n return new SafeSubscriber(next, error, complete);\n }\n next(value) {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n }\n else {\n this._next(value);\n }\n }\n error(err) {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n }\n else {\n this.isStopped = true;\n this._error(err);\n }\n }\n complete() {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n }\n else {\n this.isStopped = true;\n this._complete();\n }\n }\n unsubscribe() {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n }\n }\n _next(value) {\n this.destination.next(value);\n }\n _error(err) {\n this.destination.error(err);\n this.unsubscribe();\n }\n _complete() {\n this.destination.complete();\n this.unsubscribe();\n }\n}\nexport class SafeSubscriber extends Subscriber {\n constructor(observerOrNext, error, complete) {\n super();\n this.destination = EMPTY_OBSERVER;\n if ((observerOrNext || error || complete) && observerOrNext !== EMPTY_OBSERVER) {\n let next;\n if (isFunction(observerOrNext)) {\n next = observerOrNext;\n }\n else if (observerOrNext) {\n ({ next, error, complete } = observerOrNext);\n let context;\n if (this && config.useDeprecatedNextContext) {\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n }\n else {\n context = observerOrNext;\n }\n next = next === null || next === void 0 ? void 0 : next.bind(context);\n error = error === null || error === void 0 ? void 0 : error.bind(context);\n complete = complete === null || complete === void 0 ? void 0 : complete.bind(context);\n }\n this.destination = {\n next: next || noop,\n error: error || defaultErrorHandler,\n complete: complete || noop,\n };\n }\n }\n}\nfunction defaultErrorHandler(err) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n throw err;\n }\n reportUnhandledError(err);\n}\nfunction handleStoppedNotification(notification, subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\nexport const EMPTY_OBSERVER = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n//# sourceMappingURL=Subscriber.js.map","export const isArrayLike = ((x) => x && typeof x.length === 'number' && typeof x !== 'function');\n//# sourceMappingURL=isArrayLike.js.map","import { Observable } from '../Observable';\nexport function scheduleArray(input, scheduler) {\n return new Observable((subscriber) => {\n let i = 0;\n return scheduler.schedule(function () {\n if (i === input.length) {\n subscriber.complete();\n }\n else {\n subscriber.next(input[i++]);\n if (!subscriber.closed) {\n this.schedule();\n }\n }\n });\n });\n}\n//# sourceMappingURL=scheduleArray.js.map","import { Observable } from '../Observable';\nexport const EMPTY = new Observable(subscriber => subscriber.complete());\nexport function empty(scheduler) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\nfunction emptyScheduled(scheduler) {\n return new Observable(subscriber => scheduler.schedule(() => subscriber.complete()));\n}\n//# sourceMappingURL=empty.js.map","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\nexport const async = asyncScheduler;\n//# sourceMappingURL=async.js.map","import { createErrorClass } from './createErrorClass';\nexport const ObjectUnsubscribedError = createErrorClass((_super) => function ObjectUnsubscribedErrorImpl() {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n});\n//# sourceMappingURL=ObjectUnsubscribedError.js.map","import { Observable } from './Observable';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nexport class Subject extends Observable {\n constructor() {\n super();\n this.observers = [];\n this.closed = false;\n this.isStopped = false;\n this.hasError = false;\n this.thrownError = null;\n }\n lift(operator) {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator;\n return subject;\n }\n _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n next(value) {\n this._throwIfClosed();\n if (!this.isStopped) {\n const copy = this.observers.slice();\n for (const observer of copy) {\n observer.next(value);\n }\n }\n }\n error(err) {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift().error(err);\n }\n }\n }\n complete() {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift().complete();\n }\n }\n }\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = null;\n }\n _trySubscribe(subscriber) {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n _subscribe(subscriber) {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n _innerSubscribe(subscriber) {\n const { hasError, isStopped, observers } = this;\n return hasError || isStopped\n ? EMPTY_SUBSCRIPTION\n : (observers.push(subscriber), new Subscription(() => arrRemove(this.observers, subscriber)));\n }\n _checkFinalizedStatuses(subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n }\n else if (isStopped) {\n subscriber.complete();\n }\n }\n asObservable() {\n const observable = new Observable();\n observable.source = this;\n return observable;\n }\n}\nSubject.create = (destination, source) => {\n return new AnonymousSubject(destination, source);\n};\nexport class AnonymousSubject extends Subject {\n constructor(destination, source) {\n super();\n this.destination = destination;\n this.source = source;\n }\n next(value) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.next) === null || _b === void 0 ? void 0 : _b.call(_a, value);\n }\n error(err) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, err);\n }\n complete() {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);\n }\n _subscribe(subscriber) {\n var _a, _b;\n return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber)) !== null && _b !== void 0 ? _b : EMPTY_SUBSCRIPTION;\n }\n}\n//# sourceMappingURL=Subject.js.map","import { concatAll } from '../operators/concatAll';\nimport { internalFromArray } from './fromArray';\nimport { popScheduler } from '../util/args';\nexport function concat(...args) {\n return concatAll()(internalFromArray(args, popScheduler(args)));\n}\n//# sourceMappingURL=concat.js.map","import { mergeAll } from './mergeAll';\nexport function concatAll() {\n return mergeAll(1);\n}\n//# sourceMappingURL=concatAll.js.map","export function createErrorClass(createImpl) {\n const _super = (instance) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n//# sourceMappingURL=createErrorClass.js.map","import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\nexport function reportUnhandledError(err) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n onUnhandledError(err);\n }\n else {\n throw err;\n }\n });\n}\n//# sourceMappingURL=reportUnhandledError.js.map","export const timeoutProvider = {\n setTimeout(...args) {\n const { delegate } = timeoutProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setTimeout) || setTimeout)(...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearTimeout) || clearTimeout)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=timeoutProvider.js.map","export const dateTimestampProvider = {\n now() {\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n//# sourceMappingURL=dateTimestampProvider.js.map","import { map } from \"../operators/map\";\nconst { isArray } = Array;\nfunction callOrApply(fn, args) {\n return isArray(args) ? fn(...args) : fn(args);\n}\nexport function mapOneOrManyArgs(fn) {\n return map(args => callOrApply(fn, args));\n}\n//# sourceMappingURL=mapOneOrManyArgs.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function map(project, thisArg) {\n return operate((source, subscriber) => {\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n subscriber.next(project.call(thisArg, value, index++));\n }));\n });\n}\n//# sourceMappingURL=map.js.map","import { isFunction } from './isFunction';\nexport function isScheduler(value) {\n return value && isFunction(value.schedule);\n}\n//# sourceMappingURL=isScheduler.js.map","const { isArray } = Array;\nexport function argsOrArgArray(args) {\n return args.length === 1 && isArray(args[0]) ? args[0] : args;\n}\n//# sourceMappingURL=argsOrArgArray.js.map","import { mergeMap } from './mergeMap';\nimport { identity } from '../util/identity';\nexport function mergeAll(concurrent = Infinity) {\n return mergeMap(identity, concurrent);\n}\n//# sourceMappingURL=mergeAll.js.map","import { Subscription } from '../Subscription';\nexport class Action extends Subscription {\n constructor(scheduler, work) {\n super();\n }\n schedule(state, delay = 0) {\n return this;\n }\n}\n//# sourceMappingURL=Action.js.map","export const intervalProvider = {\n setInterval(...args) {\n const { delegate } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) || setInterval)(...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=intervalProvider.js.map","import { Action } from './Action';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nexport class AsyncAction extends Action {\n constructor(scheduler, work) {\n super(scheduler, work);\n this.scheduler = scheduler;\n this.work = work;\n this.pending = false;\n }\n schedule(state, delay = 0) {\n if (this.closed) {\n return this;\n }\n this.state = state;\n const id = this.id;\n const scheduler = this.scheduler;\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n this.pending = true;\n this.delay = delay;\n this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);\n return this;\n }\n requestAsyncId(scheduler, _id, delay = 0) {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n recycleAsyncId(_scheduler, id, delay = 0) {\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n intervalProvider.clearInterval(id);\n return undefined;\n }\n execute(state, delay) {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n }\n else if (this.pending === false && this.id != null) {\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n _execute(state, _delay) {\n let errored = false;\n let errorValue;\n try {\n this.work(state);\n }\n catch (e) {\n errored = true;\n errorValue = (!!e && e) || new Error(e);\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n this.work = this.state = this.scheduler = null;\n this.pending = false;\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n this.delay = null;\n super.unsubscribe();\n }\n }\n}\n//# sourceMappingURL=AsyncAction.js.map","import { Observable } from '../Observable';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\nexport function timer(dueTime = 0, intervalOrScheduler, scheduler = asyncScheduler) {\n let intervalDuration = -1;\n if (intervalOrScheduler != null) {\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n }\n else {\n intervalDuration = intervalOrScheduler;\n }\n }\n return new Observable((subscriber) => {\n let due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;\n if (due < 0) {\n due = 0;\n }\n let n = 0;\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n subscriber.next(n++);\n if (0 <= intervalDuration) {\n this.schedule(undefined, intervalDuration);\n }\n else {\n subscriber.complete();\n }\n }\n }, due);\n });\n}\n//# sourceMappingURL=timer.js.map","export function isValidDate(value) {\n return value instanceof Date && !isNaN(value);\n}\n//# sourceMappingURL=isDate.js.map","import { dateTimestampProvider } from \"./scheduler/dateTimestampProvider\";\nexport class Scheduler {\n constructor(schedulerActionCtor, now = Scheduler.now) {\n this.schedulerActionCtor = schedulerActionCtor;\n this.now = now;\n }\n schedule(work, delay = 0, state) {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\nScheduler.now = dateTimestampProvider.now;\n//# sourceMappingURL=Scheduler.js.map","import { Scheduler } from '../Scheduler';\nexport class AsyncScheduler extends Scheduler {\n constructor(SchedulerAction, now = Scheduler.now) {\n super(SchedulerAction, now);\n this.actions = [];\n this.active = false;\n this.scheduled = undefined;\n }\n flush(action) {\n const { actions } = this;\n if (this.active) {\n actions.push(action);\n return;\n }\n let error;\n this.active = true;\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (action = actions.shift());\n this.active = false;\n if (error) {\n while (action = actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=AsyncScheduler.js.map","import { innerFrom } from '../observable/from';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function switchMap(project, resultSelector) {\n return operate((source, subscriber) => {\n let innerSubscriber = null;\n let index = 0;\n let isComplete = false;\n const checkComplete = () => isComplete && !innerSubscriber && subscriber.complete();\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();\n let innerIndex = 0;\n const outerIndex = index++;\n innerFrom(project(value, outerIndex)).subscribe((innerSubscriber = new OperatorSubscriber(subscriber, (innerValue) => subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue), undefined, () => {\n innerSubscriber = null;\n checkComplete();\n })));\n }, undefined, () => {\n isComplete = true;\n checkComplete();\n }));\n });\n}\n//# sourceMappingURL=switchMap.js.map","import { EMPTY } from '../observable/empty';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function take(count) {\n return count <= 0\n ?\n () => EMPTY\n : operate((source, subscriber) => {\n let seen = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n if (++seen <= count) {\n subscriber.next(value);\n if (count <= seen) {\n subscriber.complete();\n }\n }\n }));\n });\n}\n//# sourceMappingURL=take.js.map","/*!\n * clipboard.js v2.0.6\n * https://clipboardjs.com/\n * \n * Licensed MIT © Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \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 = 6);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar is = __webpack_require__(3);\nvar delegate = __webpack_require__(4);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar closest = __webpack_require__(5);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n__webpack_require__.r(__webpack_exports__);\n\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(0);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n\n// CONCATENATED MODULE: ./src/clipboard-action.js\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n\n\n/**\n * Inner class which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n */\n\nvar clipboard_action_ClipboardAction = function () {\n /**\n * @param {Object} options\n */\n function ClipboardAction(options) {\n _classCallCheck(this, ClipboardAction);\n\n this.resolveOptions(options);\n this.initSelection();\n }\n\n /**\n * Defines base properties passed from constructor.\n * @param {Object} options\n */\n\n\n _createClass(ClipboardAction, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = options.action;\n this.container = options.container;\n this.emitter = options.emitter;\n this.target = options.target;\n this.text = options.text;\n this.trigger = options.trigger;\n\n this.selectedText = '';\n }\n\n /**\n * Decides which selection strategy is going to be applied based\n * on the existence of `text` and `target` properties.\n */\n\n }, {\n key: 'initSelection',\n value: function initSelection() {\n if (this.text) {\n this.selectFake();\n } else if (this.target) {\n this.selectTarget();\n }\n }\n\n /**\n * Creates a fake textarea element, sets its value from `text` property,\n * and makes a selection on it.\n */\n\n }, {\n key: 'selectFake',\n value: function selectFake() {\n var _this = this;\n\n var isRTL = document.documentElement.getAttribute('dir') == 'rtl';\n\n this.removeFake();\n\n this.fakeHandlerCallback = function () {\n return _this.removeFake();\n };\n this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;\n\n this.fakeElem = document.createElement('textarea');\n // Prevent zooming on iOS\n this.fakeElem.style.fontSize = '12pt';\n // Reset box model\n this.fakeElem.style.border = '0';\n this.fakeElem.style.padding = '0';\n this.fakeElem.style.margin = '0';\n // Move element out of screen horizontally\n this.fakeElem.style.position = 'absolute';\n this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';\n // Move element to the same position vertically\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n this.fakeElem.style.top = yPosition + 'px';\n\n this.fakeElem.setAttribute('readonly', '');\n this.fakeElem.value = this.text;\n\n this.container.appendChild(this.fakeElem);\n\n this.selectedText = select_default()(this.fakeElem);\n this.copyText();\n }\n\n /**\n * Only removes the fake element after another click event, that way\n * a user can hit `Ctrl+C` to copy because selection still exists.\n */\n\n }, {\n key: 'removeFake',\n value: function removeFake() {\n if (this.fakeHandler) {\n this.container.removeEventListener('click', this.fakeHandlerCallback);\n this.fakeHandler = null;\n this.fakeHandlerCallback = null;\n }\n\n if (this.fakeElem) {\n this.container.removeChild(this.fakeElem);\n this.fakeElem = null;\n }\n }\n\n /**\n * Selects the content from element passed on `target` property.\n */\n\n }, {\n key: 'selectTarget',\n value: function selectTarget() {\n this.selectedText = select_default()(this.target);\n this.copyText();\n }\n\n /**\n * Executes the copy operation based on the current selection.\n */\n\n }, {\n key: 'copyText',\n value: function copyText() {\n var succeeded = void 0;\n\n try {\n succeeded = document.execCommand(this.action);\n } catch (err) {\n succeeded = false;\n }\n\n this.handleResult(succeeded);\n }\n\n /**\n * Fires an event based on the copy operation result.\n * @param {Boolean} succeeded\n */\n\n }, {\n key: 'handleResult',\n value: function handleResult(succeeded) {\n this.emitter.emit(succeeded ? 'success' : 'error', {\n action: this.action,\n text: this.selectedText,\n trigger: this.trigger,\n clearSelection: this.clearSelection.bind(this)\n });\n }\n\n /**\n * Moves focus away from `target` and back to the trigger, removes current selection.\n */\n\n }, {\n key: 'clearSelection',\n value: function clearSelection() {\n if (this.trigger) {\n this.trigger.focus();\n }\n document.activeElement.blur();\n window.getSelection().removeAllRanges();\n }\n\n /**\n * Sets the `action` to be performed which can be either 'copy' or 'cut'.\n * @param {String} action\n */\n\n }, {\n key: 'destroy',\n\n\n /**\n * Destroy lifecycle.\n */\n value: function destroy() {\n this.removeFake();\n }\n }, {\n key: 'action',\n set: function set() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';\n\n this._action = action;\n\n if (this._action !== 'copy' && this._action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n }\n }\n\n /**\n * Gets the `action` property.\n * @return {String}\n */\n ,\n get: function get() {\n return this._action;\n }\n\n /**\n * Sets the `target` property using an element\n * that will be have its content copied.\n * @param {Element} target\n */\n\n }, {\n key: 'target',\n set: function set(target) {\n if (target !== undefined) {\n if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {\n if (this.action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n\n this._target = target;\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n }\n }\n\n /**\n * Gets the `target` property.\n * @return {String|HTMLElement}\n */\n ,\n get: function get() {\n return this._target;\n }\n }]);\n\n return ClipboardAction;\n}();\n\n/* harmony default export */ var clipboard_action = (clipboard_action_ClipboardAction);\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(1);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(2);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n\n// CONCATENATED MODULE: ./src/clipboard.js\nvar clipboard_typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar clipboard_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction clipboard_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n\n\n\n\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\nvar clipboard_Clipboard = function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n clipboard_classCallCheck(this, Clipboard);\n\n var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));\n\n _this.resolveOptions(options);\n _this.listenClick(trigger);\n return _this;\n }\n\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n clipboard_createClass(Clipboard, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: 'listenClick',\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: 'onClick',\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n\n if (this.clipboardAction) {\n this.clipboardAction = null;\n }\n\n this.clipboardAction = new clipboard_action({\n action: this.action(trigger),\n target: this.target(trigger),\n text: this.text(trigger),\n container: this.container,\n trigger: trigger,\n emitter: this\n });\n }\n\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultAction',\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultTarget',\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: 'defaultText',\n\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: 'destroy',\n value: function destroy() {\n this.listener.destroy();\n\n if (this.clipboardAction) {\n this.clipboardAction.destroy();\n this.clipboardAction = null;\n }\n }\n }], [{\n key: 'isSupported',\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n\n return support;\n }\n }]);\n\n return Clipboard;\n}(tiny_emitter_default.a);\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\n\nfunction getAttributeValue(suffix, element) {\n var attribute = 'data-clipboard-' + suffix;\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n\n/* harmony default export */ var clipboard = __webpack_exports__[\"default\"] = (clipboard_Clipboard);\n\n/***/ })\n/******/ ])[\"default\"];\n});","import { Subject } from './Subject';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\nexport class ReplaySubject extends Subject {\n constructor(bufferSize = Infinity, windowTime = Infinity, timestampProvider = dateTimestampProvider) {\n super();\n this.bufferSize = bufferSize;\n this.windowTime = windowTime;\n this.timestampProvider = timestampProvider;\n this.buffer = [];\n this.infiniteTimeWindow = true;\n this.infiniteTimeWindow = windowTime === Infinity;\n this.bufferSize = Math.max(1, bufferSize);\n this.windowTime = Math.max(1, windowTime);\n }\n next(value) {\n const { isStopped, buffer, infiniteTimeWindow, timestampProvider, windowTime } = this;\n if (!isStopped) {\n buffer.push(value);\n !infiniteTimeWindow && buffer.push(timestampProvider.now() + windowTime);\n }\n this.trimBuffer();\n super.next(value);\n }\n _subscribe(subscriber) {\n this._throwIfClosed();\n this.trimBuffer();\n const subscription = this._innerSubscribe(subscriber);\n const { infiniteTimeWindow, buffer } = this;\n const copy = buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i]);\n }\n this._checkFinalizedStatuses(subscriber);\n return subscription;\n }\n trimBuffer() {\n const { bufferSize, timestampProvider, buffer, infiniteTimeWindow } = this;\n const adjustedBufferSize = (infiniteTimeWindow ? 1 : 2) * bufferSize;\n bufferSize < Infinity && adjustedBufferSize < buffer.length && buffer.splice(0, buffer.length - adjustedBufferSize);\n if (!infiniteTimeWindow) {\n const now = timestampProvider.now();\n let last = 0;\n for (let i = 1; i < buffer.length && buffer[i] <= now; i += 2) {\n last = i;\n }\n last && buffer.splice(0, last + 1);\n }\n }\n}\n//# sourceMappingURL=ReplaySubject.js.map","import { identity } from './identity';\nexport function pipe(...fns) {\n return pipeFromArray(fns);\n}\nexport function pipeFromArray(fns) {\n if (fns.length === 0) {\n return identity;\n }\n if (fns.length === 1) {\n return fns[0];\n }\n return function piped(input) {\n return fns.reduce((prev, fn) => fn(prev), input);\n };\n}\n//# sourceMappingURL=pipe.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function mapTo(value) {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, () => subscriber.next(value)));\n });\n}\n//# sourceMappingURL=mapTo.js.map","/**\r\n * A collection of shims that provide minimal functionality of the ES6 collections.\r\n *\r\n * These implementations are not meant to be used outside of the ResizeObserver\r\n * modules as they cover only a limited range of use cases.\r\n */\r\n/* eslint-disable require-jsdoc, valid-jsdoc */\r\nvar MapShim = (function () {\r\n if (typeof Map !== 'undefined') {\r\n return Map;\r\n }\r\n /**\r\n * Returns index in provided array that matches the specified key.\r\n *\r\n * @param {Array} arr\r\n * @param {*} key\r\n * @returns {number}\r\n */\r\n function getIndex(arr, key) {\r\n var result = -1;\r\n arr.some(function (entry, index) {\r\n if (entry[0] === key) {\r\n result = index;\r\n return true;\r\n }\r\n return false;\r\n });\r\n return result;\r\n }\r\n return /** @class */ (function () {\r\n function class_1() {\r\n this.__entries__ = [];\r\n }\r\n Object.defineProperty(class_1.prototype, \"size\", {\r\n /**\r\n * @returns {boolean}\r\n */\r\n get: function () {\r\n return this.__entries__.length;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * @param {*} key\r\n * @returns {*}\r\n */\r\n class_1.prototype.get = function (key) {\r\n var index = getIndex(this.__entries__, key);\r\n var entry = this.__entries__[index];\r\n return entry && entry[1];\r\n };\r\n /**\r\n * @param {*} key\r\n * @param {*} value\r\n * @returns {void}\r\n */\r\n class_1.prototype.set = function (key, value) {\r\n var index = getIndex(this.__entries__, key);\r\n if (~index) {\r\n this.__entries__[index][1] = value;\r\n }\r\n else {\r\n this.__entries__.push([key, value]);\r\n }\r\n };\r\n /**\r\n * @param {*} key\r\n * @returns {void}\r\n */\r\n class_1.prototype.delete = function (key) {\r\n var entries = this.__entries__;\r\n var index = getIndex(entries, key);\r\n if (~index) {\r\n entries.splice(index, 1);\r\n }\r\n };\r\n /**\r\n * @param {*} key\r\n * @returns {void}\r\n */\r\n class_1.prototype.has = function (key) {\r\n return !!~getIndex(this.__entries__, key);\r\n };\r\n /**\r\n * @returns {void}\r\n */\r\n class_1.prototype.clear = function () {\r\n this.__entries__.splice(0);\r\n };\r\n /**\r\n * @param {Function} callback\r\n * @param {*} [ctx=null]\r\n * @returns {void}\r\n */\r\n class_1.prototype.forEach = function (callback, ctx) {\r\n if (ctx === void 0) { ctx = null; }\r\n for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) {\r\n var entry = _a[_i];\r\n callback.call(ctx, entry[1], entry[0]);\r\n }\r\n };\r\n return class_1;\r\n }());\r\n})();\n\n/**\r\n * Detects whether window and document objects are available in current environment.\r\n */\r\nvar isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document;\n\n// Returns global object of a current environment.\r\nvar global$1 = (function () {\r\n if (typeof global !== 'undefined' && global.Math === Math) {\r\n return global;\r\n }\r\n if (typeof self !== 'undefined' && self.Math === Math) {\r\n return self;\r\n }\r\n if (typeof window !== 'undefined' && window.Math === Math) {\r\n return window;\r\n }\r\n // eslint-disable-next-line no-new-func\r\n return Function('return this')();\r\n})();\n\n/**\r\n * A shim for the requestAnimationFrame which falls back to the setTimeout if\r\n * first one is not supported.\r\n *\r\n * @returns {number} Requests' identifier.\r\n */\r\nvar requestAnimationFrame$1 = (function () {\r\n if (typeof requestAnimationFrame === 'function') {\r\n // It's required to use a bounded function because IE sometimes throws\r\n // an \"Invalid calling object\" error if rAF is invoked without the global\r\n // object on the left hand side.\r\n return requestAnimationFrame.bind(global$1);\r\n }\r\n return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); };\r\n})();\n\n// Defines minimum timeout before adding a trailing call.\r\nvar trailingTimeout = 2;\r\n/**\r\n * Creates a wrapper function which ensures that provided callback will be\r\n * invoked only once during the specified delay period.\r\n *\r\n * @param {Function} callback - Function to be invoked after the delay period.\r\n * @param {number} delay - Delay after which to invoke callback.\r\n * @returns {Function}\r\n */\r\nfunction throttle (callback, delay) {\r\n var leadingCall = false, trailingCall = false, lastCallTime = 0;\r\n /**\r\n * Invokes the original callback function and schedules new invocation if\r\n * the \"proxy\" was called during current request.\r\n *\r\n * @returns {void}\r\n */\r\n function resolvePending() {\r\n if (leadingCall) {\r\n leadingCall = false;\r\n callback();\r\n }\r\n if (trailingCall) {\r\n proxy();\r\n }\r\n }\r\n /**\r\n * Callback invoked after the specified delay. It will further postpone\r\n * invocation of the original function delegating it to the\r\n * requestAnimationFrame.\r\n *\r\n * @returns {void}\r\n */\r\n function timeoutCallback() {\r\n requestAnimationFrame$1(resolvePending);\r\n }\r\n /**\r\n * Schedules invocation of the original function.\r\n *\r\n * @returns {void}\r\n */\r\n function proxy() {\r\n var timeStamp = Date.now();\r\n if (leadingCall) {\r\n // Reject immediately following calls.\r\n if (timeStamp - lastCallTime < trailingTimeout) {\r\n return;\r\n }\r\n // Schedule new call to be in invoked when the pending one is resolved.\r\n // This is important for \"transitions\" which never actually start\r\n // immediately so there is a chance that we might miss one if change\r\n // happens amids the pending invocation.\r\n trailingCall = true;\r\n }\r\n else {\r\n leadingCall = true;\r\n trailingCall = false;\r\n setTimeout(timeoutCallback, delay);\r\n }\r\n lastCallTime = timeStamp;\r\n }\r\n return proxy;\r\n}\n\n// Minimum delay before invoking the update of observers.\r\nvar REFRESH_DELAY = 20;\r\n// A list of substrings of CSS properties used to find transition events that\r\n// might affect dimensions of observed elements.\r\nvar transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight'];\r\n// Check if MutationObserver is available.\r\nvar mutationObserverSupported = typeof MutationObserver !== 'undefined';\r\n/**\r\n * Singleton controller class which handles updates of ResizeObserver instances.\r\n */\r\nvar ResizeObserverController = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserverController.\r\n *\r\n * @private\r\n */\r\n function ResizeObserverController() {\r\n /**\r\n * Indicates whether DOM listeners have been added.\r\n *\r\n * @private {boolean}\r\n */\r\n this.connected_ = false;\r\n /**\r\n * Tells that controller has subscribed for Mutation Events.\r\n *\r\n * @private {boolean}\r\n */\r\n this.mutationEventsAdded_ = false;\r\n /**\r\n * Keeps reference to the instance of MutationObserver.\r\n *\r\n * @private {MutationObserver}\r\n */\r\n this.mutationsObserver_ = null;\r\n /**\r\n * A list of connected observers.\r\n *\r\n * @private {Array}\r\n */\r\n this.observers_ = [];\r\n this.onTransitionEnd_ = this.onTransitionEnd_.bind(this);\r\n this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);\r\n }\r\n /**\r\n * Adds observer to observers list.\r\n *\r\n * @param {ResizeObserverSPI} observer - Observer to be added.\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.addObserver = function (observer) {\r\n if (!~this.observers_.indexOf(observer)) {\r\n this.observers_.push(observer);\r\n }\r\n // Add listeners if they haven't been added yet.\r\n if (!this.connected_) {\r\n this.connect_();\r\n }\r\n };\r\n /**\r\n * Removes observer from observers list.\r\n *\r\n * @param {ResizeObserverSPI} observer - Observer to be removed.\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.removeObserver = function (observer) {\r\n var observers = this.observers_;\r\n var index = observers.indexOf(observer);\r\n // Remove observer if it's present in registry.\r\n if (~index) {\r\n observers.splice(index, 1);\r\n }\r\n // Remove listeners if controller has no connected observers.\r\n if (!observers.length && this.connected_) {\r\n this.disconnect_();\r\n }\r\n };\r\n /**\r\n * Invokes the update of observers. It will continue running updates insofar\r\n * it detects changes.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.refresh = function () {\r\n var changesDetected = this.updateObservers_();\r\n // Continue running updates if changes have been detected as there might\r\n // be future ones caused by CSS transitions.\r\n if (changesDetected) {\r\n this.refresh();\r\n }\r\n };\r\n /**\r\n * Updates every observer from observers list and notifies them of queued\r\n * entries.\r\n *\r\n * @private\r\n * @returns {boolean} Returns \"true\" if any observer has detected changes in\r\n * dimensions of it's elements.\r\n */\r\n ResizeObserverController.prototype.updateObservers_ = function () {\r\n // Collect observers that have active observations.\r\n var activeObservers = this.observers_.filter(function (observer) {\r\n return observer.gatherActive(), observer.hasActive();\r\n });\r\n // Deliver notifications in a separate cycle in order to avoid any\r\n // collisions between observers, e.g. when multiple instances of\r\n // ResizeObserver are tracking the same element and the callback of one\r\n // of them changes content dimensions of the observed target. Sometimes\r\n // this may result in notifications being blocked for the rest of observers.\r\n activeObservers.forEach(function (observer) { return observer.broadcastActive(); });\r\n return activeObservers.length > 0;\r\n };\r\n /**\r\n * Initializes DOM listeners.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.connect_ = function () {\r\n // Do nothing if running in a non-browser environment or if listeners\r\n // have been already added.\r\n if (!isBrowser || this.connected_) {\r\n return;\r\n }\r\n // Subscription to the \"Transitionend\" event is used as a workaround for\r\n // delayed transitions. This way it's possible to capture at least the\r\n // final state of an element.\r\n document.addEventListener('transitionend', this.onTransitionEnd_);\r\n window.addEventListener('resize', this.refresh);\r\n if (mutationObserverSupported) {\r\n this.mutationsObserver_ = new MutationObserver(this.refresh);\r\n this.mutationsObserver_.observe(document, {\r\n attributes: true,\r\n childList: true,\r\n characterData: true,\r\n subtree: true\r\n });\r\n }\r\n else {\r\n document.addEventListener('DOMSubtreeModified', this.refresh);\r\n this.mutationEventsAdded_ = true;\r\n }\r\n this.connected_ = true;\r\n };\r\n /**\r\n * Removes DOM listeners.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.disconnect_ = function () {\r\n // Do nothing if running in a non-browser environment or if listeners\r\n // have been already removed.\r\n if (!isBrowser || !this.connected_) {\r\n return;\r\n }\r\n document.removeEventListener('transitionend', this.onTransitionEnd_);\r\n window.removeEventListener('resize', this.refresh);\r\n if (this.mutationsObserver_) {\r\n this.mutationsObserver_.disconnect();\r\n }\r\n if (this.mutationEventsAdded_) {\r\n document.removeEventListener('DOMSubtreeModified', this.refresh);\r\n }\r\n this.mutationsObserver_ = null;\r\n this.mutationEventsAdded_ = false;\r\n this.connected_ = false;\r\n };\r\n /**\r\n * \"Transitionend\" event handler.\r\n *\r\n * @private\r\n * @param {TransitionEvent} event\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.onTransitionEnd_ = function (_a) {\r\n var _b = _a.propertyName, propertyName = _b === void 0 ? '' : _b;\r\n // Detect whether transition may affect dimensions of an element.\r\n var isReflowProperty = transitionKeys.some(function (key) {\r\n return !!~propertyName.indexOf(key);\r\n });\r\n if (isReflowProperty) {\r\n this.refresh();\r\n }\r\n };\r\n /**\r\n * Returns instance of the ResizeObserverController.\r\n *\r\n * @returns {ResizeObserverController}\r\n */\r\n ResizeObserverController.getInstance = function () {\r\n if (!this.instance_) {\r\n this.instance_ = new ResizeObserverController();\r\n }\r\n return this.instance_;\r\n };\r\n /**\r\n * Holds reference to the controller's instance.\r\n *\r\n * @private {ResizeObserverController}\r\n */\r\n ResizeObserverController.instance_ = null;\r\n return ResizeObserverController;\r\n}());\n\n/**\r\n * Defines non-writable/enumerable properties of the provided target object.\r\n *\r\n * @param {Object} target - Object for which to define properties.\r\n * @param {Object} props - Properties to be defined.\r\n * @returns {Object} Target object.\r\n */\r\nvar defineConfigurable = (function (target, props) {\r\n for (var _i = 0, _a = Object.keys(props); _i < _a.length; _i++) {\r\n var key = _a[_i];\r\n Object.defineProperty(target, key, {\r\n value: props[key],\r\n enumerable: false,\r\n writable: false,\r\n configurable: true\r\n });\r\n }\r\n return target;\r\n});\n\n/**\r\n * Returns the global object associated with provided element.\r\n *\r\n * @param {Object} target\r\n * @returns {Object}\r\n */\r\nvar getWindowOf = (function (target) {\r\n // Assume that the element is an instance of Node, which means that it\r\n // has the \"ownerDocument\" property from which we can retrieve a\r\n // corresponding global object.\r\n var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView;\r\n // Return the local global object if it's not possible extract one from\r\n // provided element.\r\n return ownerGlobal || global$1;\r\n});\n\n// Placeholder of an empty content rectangle.\r\nvar emptyRect = createRectInit(0, 0, 0, 0);\r\n/**\r\n * Converts provided string to a number.\r\n *\r\n * @param {number|string} value\r\n * @returns {number}\r\n */\r\nfunction toFloat(value) {\r\n return parseFloat(value) || 0;\r\n}\r\n/**\r\n * Extracts borders size from provided styles.\r\n *\r\n * @param {CSSStyleDeclaration} styles\r\n * @param {...string} positions - Borders positions (top, right, ...)\r\n * @returns {number}\r\n */\r\nfunction getBordersSize(styles) {\r\n var positions = [];\r\n for (var _i = 1; _i < arguments.length; _i++) {\r\n positions[_i - 1] = arguments[_i];\r\n }\r\n return positions.reduce(function (size, position) {\r\n var value = styles['border-' + position + '-width'];\r\n return size + toFloat(value);\r\n }, 0);\r\n}\r\n/**\r\n * Extracts paddings sizes from provided styles.\r\n *\r\n * @param {CSSStyleDeclaration} styles\r\n * @returns {Object} Paddings box.\r\n */\r\nfunction getPaddings(styles) {\r\n var positions = ['top', 'right', 'bottom', 'left'];\r\n var paddings = {};\r\n for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {\r\n var position = positions_1[_i];\r\n var value = styles['padding-' + position];\r\n paddings[position] = toFloat(value);\r\n }\r\n return paddings;\r\n}\r\n/**\r\n * Calculates content rectangle of provided SVG element.\r\n *\r\n * @param {SVGGraphicsElement} target - Element content rectangle of which needs\r\n * to be calculated.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getSVGContentRect(target) {\r\n var bbox = target.getBBox();\r\n return createRectInit(0, 0, bbox.width, bbox.height);\r\n}\r\n/**\r\n * Calculates content rectangle of provided HTMLElement.\r\n *\r\n * @param {HTMLElement} target - Element for which to calculate the content rectangle.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getHTMLElementContentRect(target) {\r\n // Client width & height properties can't be\r\n // used exclusively as they provide rounded values.\r\n var clientWidth = target.clientWidth, clientHeight = target.clientHeight;\r\n // By this condition we can catch all non-replaced inline, hidden and\r\n // detached elements. Though elements with width & height properties less\r\n // than 0.5 will be discarded as well.\r\n //\r\n // Without it we would need to implement separate methods for each of\r\n // those cases and it's not possible to perform a precise and performance\r\n // effective test for hidden elements. E.g. even jQuery's ':visible' filter\r\n // gives wrong results for elements with width & height less than 0.5.\r\n if (!clientWidth && !clientHeight) {\r\n return emptyRect;\r\n }\r\n var styles = getWindowOf(target).getComputedStyle(target);\r\n var paddings = getPaddings(styles);\r\n var horizPad = paddings.left + paddings.right;\r\n var vertPad = paddings.top + paddings.bottom;\r\n // Computed styles of width & height are being used because they are the\r\n // only dimensions available to JS that contain non-rounded values. It could\r\n // be possible to utilize the getBoundingClientRect if only it's data wasn't\r\n // affected by CSS transformations let alone paddings, borders and scroll bars.\r\n var width = toFloat(styles.width), height = toFloat(styles.height);\r\n // Width & height include paddings and borders when the 'border-box' box\r\n // model is applied (except for IE).\r\n if (styles.boxSizing === 'border-box') {\r\n // Following conditions are required to handle Internet Explorer which\r\n // doesn't include paddings and borders to computed CSS dimensions.\r\n //\r\n // We can say that if CSS dimensions + paddings are equal to the \"client\"\r\n // properties then it's either IE, and thus we don't need to subtract\r\n // anything, or an element merely doesn't have paddings/borders styles.\r\n if (Math.round(width + horizPad) !== clientWidth) {\r\n width -= getBordersSize(styles, 'left', 'right') + horizPad;\r\n }\r\n if (Math.round(height + vertPad) !== clientHeight) {\r\n height -= getBordersSize(styles, 'top', 'bottom') + vertPad;\r\n }\r\n }\r\n // Following steps can't be applied to the document's root element as its\r\n // client[Width/Height] properties represent viewport area of the window.\r\n // Besides, it's as well not necessary as the itself neither has\r\n // rendered scroll bars nor it can be clipped.\r\n if (!isDocumentElement(target)) {\r\n // In some browsers (only in Firefox, actually) CSS width & height\r\n // include scroll bars size which can be removed at this step as scroll\r\n // bars are the only difference between rounded dimensions + paddings\r\n // and \"client\" properties, though that is not always true in Chrome.\r\n var vertScrollbar = Math.round(width + horizPad) - clientWidth;\r\n var horizScrollbar = Math.round(height + vertPad) - clientHeight;\r\n // Chrome has a rather weird rounding of \"client\" properties.\r\n // E.g. for an element with content width of 314.2px it sometimes gives\r\n // the client width of 315px and for the width of 314.7px it may give\r\n // 314px. And it doesn't happen all the time. So just ignore this delta\r\n // as a non-relevant.\r\n if (Math.abs(vertScrollbar) !== 1) {\r\n width -= vertScrollbar;\r\n }\r\n if (Math.abs(horizScrollbar) !== 1) {\r\n height -= horizScrollbar;\r\n }\r\n }\r\n return createRectInit(paddings.left, paddings.top, width, height);\r\n}\r\n/**\r\n * Checks whether provided element is an instance of the SVGGraphicsElement.\r\n *\r\n * @param {Element} target - Element to be checked.\r\n * @returns {boolean}\r\n */\r\nvar isSVGGraphicsElement = (function () {\r\n // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement\r\n // interface.\r\n if (typeof SVGGraphicsElement !== 'undefined') {\r\n return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; };\r\n }\r\n // If it's so, then check that element is at least an instance of the\r\n // SVGElement and that it has the \"getBBox\" method.\r\n // eslint-disable-next-line no-extra-parens\r\n return function (target) { return (target instanceof getWindowOf(target).SVGElement &&\r\n typeof target.getBBox === 'function'); };\r\n})();\r\n/**\r\n * Checks whether provided element is a document element ().\r\n *\r\n * @param {Element} target - Element to be checked.\r\n * @returns {boolean}\r\n */\r\nfunction isDocumentElement(target) {\r\n return target === getWindowOf(target).document.documentElement;\r\n}\r\n/**\r\n * Calculates an appropriate content rectangle for provided html or svg element.\r\n *\r\n * @param {Element} target - Element content rectangle of which needs to be calculated.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getContentRect(target) {\r\n if (!isBrowser) {\r\n return emptyRect;\r\n }\r\n if (isSVGGraphicsElement(target)) {\r\n return getSVGContentRect(target);\r\n }\r\n return getHTMLElementContentRect(target);\r\n}\r\n/**\r\n * Creates rectangle with an interface of the DOMRectReadOnly.\r\n * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly\r\n *\r\n * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions.\r\n * @returns {DOMRectReadOnly}\r\n */\r\nfunction createReadOnlyRect(_a) {\r\n var x = _a.x, y = _a.y, width = _a.width, height = _a.height;\r\n // If DOMRectReadOnly is available use it as a prototype for the rectangle.\r\n var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object;\r\n var rect = Object.create(Constr.prototype);\r\n // Rectangle's properties are not writable and non-enumerable.\r\n defineConfigurable(rect, {\r\n x: x, y: y, width: width, height: height,\r\n top: y,\r\n right: x + width,\r\n bottom: height + y,\r\n left: x\r\n });\r\n return rect;\r\n}\r\n/**\r\n * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates.\r\n * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit\r\n *\r\n * @param {number} x - X coordinate.\r\n * @param {number} y - Y coordinate.\r\n * @param {number} width - Rectangle's width.\r\n * @param {number} height - Rectangle's height.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction createRectInit(x, y, width, height) {\r\n return { x: x, y: y, width: width, height: height };\r\n}\n\n/**\r\n * Class that is responsible for computations of the content rectangle of\r\n * provided DOM element and for keeping track of it's changes.\r\n */\r\nvar ResizeObservation = /** @class */ (function () {\r\n /**\r\n * Creates an instance of ResizeObservation.\r\n *\r\n * @param {Element} target - Element to be observed.\r\n */\r\n function ResizeObservation(target) {\r\n /**\r\n * Broadcasted width of content rectangle.\r\n *\r\n * @type {number}\r\n */\r\n this.broadcastWidth = 0;\r\n /**\r\n * Broadcasted height of content rectangle.\r\n *\r\n * @type {number}\r\n */\r\n this.broadcastHeight = 0;\r\n /**\r\n * Reference to the last observed content rectangle.\r\n *\r\n * @private {DOMRectInit}\r\n */\r\n this.contentRect_ = createRectInit(0, 0, 0, 0);\r\n this.target = target;\r\n }\r\n /**\r\n * Updates content rectangle and tells whether it's width or height properties\r\n * have changed since the last broadcast.\r\n *\r\n * @returns {boolean}\r\n */\r\n ResizeObservation.prototype.isActive = function () {\r\n var rect = getContentRect(this.target);\r\n this.contentRect_ = rect;\r\n return (rect.width !== this.broadcastWidth ||\r\n rect.height !== this.broadcastHeight);\r\n };\r\n /**\r\n * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data\r\n * from the corresponding properties of the last observed content rectangle.\r\n *\r\n * @returns {DOMRectInit} Last observed content rectangle.\r\n */\r\n ResizeObservation.prototype.broadcastRect = function () {\r\n var rect = this.contentRect_;\r\n this.broadcastWidth = rect.width;\r\n this.broadcastHeight = rect.height;\r\n return rect;\r\n };\r\n return ResizeObservation;\r\n}());\n\nvar ResizeObserverEntry = /** @class */ (function () {\r\n /**\r\n * Creates an instance of ResizeObserverEntry.\r\n *\r\n * @param {Element} target - Element that is being observed.\r\n * @param {DOMRectInit} rectInit - Data of the element's content rectangle.\r\n */\r\n function ResizeObserverEntry(target, rectInit) {\r\n var contentRect = createReadOnlyRect(rectInit);\r\n // According to the specification following properties are not writable\r\n // and are also not enumerable in the native implementation.\r\n //\r\n // Property accessors are not being used as they'd require to define a\r\n // private WeakMap storage which may cause memory leaks in browsers that\r\n // don't support this type of collections.\r\n defineConfigurable(this, { target: target, contentRect: contentRect });\r\n }\r\n return ResizeObserverEntry;\r\n}());\n\nvar ResizeObserverSPI = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserver.\r\n *\r\n * @param {ResizeObserverCallback} callback - Callback function that is invoked\r\n * when one of the observed elements changes it's content dimensions.\r\n * @param {ResizeObserverController} controller - Controller instance which\r\n * is responsible for the updates of observer.\r\n * @param {ResizeObserver} callbackCtx - Reference to the public\r\n * ResizeObserver instance which will be passed to callback function.\r\n */\r\n function ResizeObserverSPI(callback, controller, callbackCtx) {\r\n /**\r\n * Collection of resize observations that have detected changes in dimensions\r\n * of elements.\r\n *\r\n * @private {Array}\r\n */\r\n this.activeObservations_ = [];\r\n /**\r\n * Registry of the ResizeObservation instances.\r\n *\r\n * @private {Map}\r\n */\r\n this.observations_ = new MapShim();\r\n if (typeof callback !== 'function') {\r\n throw new TypeError('The callback provided as parameter 1 is not a function.');\r\n }\r\n this.callback_ = callback;\r\n this.controller_ = controller;\r\n this.callbackCtx_ = callbackCtx;\r\n }\r\n /**\r\n * Starts observing provided element.\r\n *\r\n * @param {Element} target - Element to be observed.\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.observe = function (target) {\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n // Do nothing if current environment doesn't have the Element interface.\r\n if (typeof Element === 'undefined' || !(Element instanceof Object)) {\r\n return;\r\n }\r\n if (!(target instanceof getWindowOf(target).Element)) {\r\n throw new TypeError('parameter 1 is not of type \"Element\".');\r\n }\r\n var observations = this.observations_;\r\n // Do nothing if element is already being observed.\r\n if (observations.has(target)) {\r\n return;\r\n }\r\n observations.set(target, new ResizeObservation(target));\r\n this.controller_.addObserver(this);\r\n // Force the update of observations.\r\n this.controller_.refresh();\r\n };\r\n /**\r\n * Stops observing provided element.\r\n *\r\n * @param {Element} target - Element to stop observing.\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.unobserve = function (target) {\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n // Do nothing if current environment doesn't have the Element interface.\r\n if (typeof Element === 'undefined' || !(Element instanceof Object)) {\r\n return;\r\n }\r\n if (!(target instanceof getWindowOf(target).Element)) {\r\n throw new TypeError('parameter 1 is not of type \"Element\".');\r\n }\r\n var observations = this.observations_;\r\n // Do nothing if element is not being observed.\r\n if (!observations.has(target)) {\r\n return;\r\n }\r\n observations.delete(target);\r\n if (!observations.size) {\r\n this.controller_.removeObserver(this);\r\n }\r\n };\r\n /**\r\n * Stops observing all elements.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.disconnect = function () {\r\n this.clearActive();\r\n this.observations_.clear();\r\n this.controller_.removeObserver(this);\r\n };\r\n /**\r\n * Collects observation instances the associated element of which has changed\r\n * it's content rectangle.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.gatherActive = function () {\r\n var _this = this;\r\n this.clearActive();\r\n this.observations_.forEach(function (observation) {\r\n if (observation.isActive()) {\r\n _this.activeObservations_.push(observation);\r\n }\r\n });\r\n };\r\n /**\r\n * Invokes initial callback function with a list of ResizeObserverEntry\r\n * instances collected from active resize observations.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.broadcastActive = function () {\r\n // Do nothing if observer doesn't have active observations.\r\n if (!this.hasActive()) {\r\n return;\r\n }\r\n var ctx = this.callbackCtx_;\r\n // Create ResizeObserverEntry instance for every active observation.\r\n var entries = this.activeObservations_.map(function (observation) {\r\n return new ResizeObserverEntry(observation.target, observation.broadcastRect());\r\n });\r\n this.callback_.call(ctx, entries, ctx);\r\n this.clearActive();\r\n };\r\n /**\r\n * Clears the collection of active observations.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.clearActive = function () {\r\n this.activeObservations_.splice(0);\r\n };\r\n /**\r\n * Tells whether observer has active observations.\r\n *\r\n * @returns {boolean}\r\n */\r\n ResizeObserverSPI.prototype.hasActive = function () {\r\n return this.activeObservations_.length > 0;\r\n };\r\n return ResizeObserverSPI;\r\n}());\n\n// Registry of internal observers. If WeakMap is not available use current shim\r\n// for the Map collection as it has all required methods and because WeakMap\r\n// can't be fully polyfilled anyway.\r\nvar observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim();\r\n/**\r\n * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation\r\n * exposing only those methods and properties that are defined in the spec.\r\n */\r\nvar ResizeObserver = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserver.\r\n *\r\n * @param {ResizeObserverCallback} callback - Callback that is invoked when\r\n * dimensions of the observed elements change.\r\n */\r\n function ResizeObserver(callback) {\r\n if (!(this instanceof ResizeObserver)) {\r\n throw new TypeError('Cannot call a class as a function.');\r\n }\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n var controller = ResizeObserverController.getInstance();\r\n var observer = new ResizeObserverSPI(callback, controller, this);\r\n observers.set(this, observer);\r\n }\r\n return ResizeObserver;\r\n}());\r\n// Expose public methods of ResizeObserver.\r\n[\r\n 'observe',\r\n 'unobserve',\r\n 'disconnect'\r\n].forEach(function (method) {\r\n ResizeObserver.prototype[method] = function () {\r\n var _a;\r\n return (_a = observers.get(this))[method].apply(_a, arguments);\r\n };\r\n});\n\nvar index = (function () {\r\n // Export existing implementation if available.\r\n if (typeof global$1.ResizeObserver !== 'undefined') {\r\n return global$1.ResizeObserver;\r\n }\r\n return ResizeObserver;\r\n})();\n\nexport default index;\n","import { Observable } from '../Observable';\nimport { innerFrom } from './from';\nexport function defer(observableFactory) {\n return new Observable((subscriber) => {\n innerFrom(observableFactory()).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=defer.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function filter(predicate, thisArg) {\n return operate((source, subscriber) => {\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => predicate.call(thisArg, value, index++) && subscriber.next(value)));\n });\n}\n//# sourceMappingURL=filter.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function distinctUntilChanged(compare, keySelector) {\n compare = compare !== null && compare !== void 0 ? compare : defaultCompare;\n return operate((source, subscriber) => {\n let prev;\n let first = true;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n ((first && ((prev = value), 1)) || !compare(prev, (prev = keySelector ? keySelector(value) : value))) &&\n subscriber.next(value);\n first = false;\n }));\n });\n}\nfunction defaultCompare(a, b) {\n return a === b;\n}\n//# sourceMappingURL=distinctUntilChanged.js.map","/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. ¯\\_(ツ)_/¯\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","import { Observable } from '../Observable';\nimport { mergeMap } from '../operators/mergeMap';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isFunction } from '../util/isFunction';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { internalFromArray } from './fromArray';\nconst nodeEventEmitterMethods = ['addListener', 'removeListener'];\nconst eventTargetMethods = ['addEventListener', 'removeEventListener'];\nconst jqueryMethods = ['on', 'off'];\nexport function fromEvent(target, eventName, options, resultSelector) {\n if (isFunction(options)) {\n resultSelector = options;\n options = undefined;\n }\n if (resultSelector) {\n return fromEvent(target, eventName, options).pipe(mapOneOrManyArgs(resultSelector));\n }\n const [add, remove] = isEventTarget(target)\n ? eventTargetMethods.map((methodName) => (handler) => target[methodName](eventName, handler, options))\n :\n isNodeStyleEventEmitter(target)\n ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName))\n : isJQueryStyleEventEmitter(target)\n ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName))\n : [];\n if (!add) {\n if (isArrayLike(target)) {\n return mergeMap((subTarget) => fromEvent(subTarget, eventName, options))(internalFromArray(target));\n }\n }\n return new Observable((subscriber) => {\n if (!add) {\n throw new TypeError('Invalid event target');\n }\n const handler = (...args) => subscriber.next(1 < args.length ? args : args[0]);\n add(handler);\n return () => remove(handler);\n });\n}\nfunction toCommonHandlerRegistry(target, eventName) {\n return (methodName) => (handler) => target[methodName](eventName, handler);\n}\nfunction isNodeStyleEventEmitter(target) {\n return isFunction(target.addListener) && isFunction(target.removeListener);\n}\nfunction isJQueryStyleEventEmitter(target) {\n return isFunction(target.on) && isFunction(target.off);\n}\nfunction isEventTarget(target) {\n return isFunction(target.addEventListener) && isFunction(target.removeEventListener);\n}\n//# sourceMappingURL=fromEvent.js.map","import { mergeAll } from '../operators/mergeAll';\nimport { internalFromArray } from './fromArray';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { innerFrom } from './from';\nimport { EMPTY } from './empty';\nimport { popNumber, popScheduler } from '../util/args';\nexport function merge(...args) {\n const scheduler = popScheduler(args);\n const concurrent = popNumber(args, Infinity);\n const sources = argsOrArgArray(args);\n return !sources.length\n ?\n EMPTY\n : sources.length === 1\n ?\n innerFrom(sources[0])\n :\n mergeAll(concurrent)(internalFromArray(sources, scheduler));\n}\n//# sourceMappingURL=merge.js.map","import { concat } from '../observable/concat';\nimport { popScheduler } from '../util/args';\nimport { operate } from '../util/lift';\nexport function startWith(...values) {\n const scheduler = popScheduler(values);\n return operate((source, subscriber) => {\n (scheduler ? concat(values, source, scheduler) : concat(values, source)).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=startWith.js.map","import { internalFromArray } from './fromArray';\nimport { scheduleArray } from '../scheduled/scheduleArray';\nimport { popScheduler } from '../util/args';\nexport function of(...args) {\n const scheduler = popScheduler(args);\n return scheduler ? scheduleArray(args, scheduler) : internalFromArray(args);\n}\n//# sourceMappingURL=of.js.map","import { Observable } from '../Observable';\nimport { noop } from '../util/noop';\nexport const NEVER = new Observable(noop);\nexport function never() {\n return NEVER;\n}\n//# sourceMappingURL=never.js.map","import { operate } from '../util/lift';\nexport function finalize(callback) {\n return operate((source, subscriber) => {\n source.subscribe(subscriber);\n subscriber.add(callback);\n });\n}\n//# sourceMappingURL=finalize.js.map","import { ReplaySubject } from '../ReplaySubject';\nimport { operate } from '../util/lift';\nexport function shareReplay(configOrBufferSize, windowTime, scheduler) {\n let config;\n if (configOrBufferSize && typeof configOrBufferSize === 'object') {\n config = configOrBufferSize;\n }\n else {\n config = {\n bufferSize: configOrBufferSize,\n windowTime,\n refCount: false,\n scheduler\n };\n }\n return operate(shareReplayOperator(config));\n}\nfunction shareReplayOperator({ bufferSize = Infinity, windowTime = Infinity, refCount: useRefCount, scheduler }) {\n let subject;\n let refCount = 0;\n let subscription;\n return (source, subscriber) => {\n refCount++;\n let innerSub;\n if (!subject) {\n subject = new ReplaySubject(bufferSize, windowTime, scheduler);\n innerSub = subject.subscribe(subscriber);\n subscription = source.subscribe({\n next(value) { subject.next(value); },\n error(err) {\n const dest = subject;\n subscription = undefined;\n subject = undefined;\n dest.error(err);\n },\n complete() {\n subscription = undefined;\n subject.complete();\n },\n });\n if (subscription.closed) {\n subscription = undefined;\n }\n }\n else {\n innerSub = subject.subscribe(subscriber);\n }\n subscriber.add(() => {\n refCount--;\n innerSub.unsubscribe();\n if (useRefCount && refCount === 0 && subscription) {\n subscription.unsubscribe();\n subscription = undefined;\n subject = undefined;\n }\n });\n };\n}\n//# sourceMappingURL=shareReplay.js.map","import { isFunction } from '../util/isFunction';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { identity } from '../util/identity';\nexport function tap(observerOrNext, error, complete) {\n const tapObserver = isFunction(observerOrNext) || error || complete ? { next: observerOrNext, error, complete } : observerOrNext;\n return tapObserver\n ? operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n var _a;\n (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);\n subscriber.next(value);\n }, (err) => {\n var _a;\n (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);\n subscriber.error(err);\n }, () => {\n var _a;\n (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);\n subscriber.complete();\n }));\n })\n :\n identity;\n}\n//# sourceMappingURL=tap.js.map","import { Subject } from './Subject';\nexport class BehaviorSubject extends Subject {\n constructor(_value) {\n super();\n this._value = _value;\n }\n get value() {\n return this.getValue();\n }\n _subscribe(subscriber) {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n getValue() {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n next(value) {\n super.next((this._value = value));\n }\n}\n//# sourceMappingURL=BehaviorSubject.js.map","import { distinctUntilChanged } from './distinctUntilChanged';\nexport function distinctUntilKeyChanged(key, compare) {\n return distinctUntilChanged((x, y) => compare ? compare(x[key], y[key]) : x[key] === y[key]);\n}\n//# sourceMappingURL=distinctUntilKeyChanged.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nexport const defaultThrottleConfig = {\n leading: true,\n trailing: false,\n};\nexport function throttle(durationSelector, { leading, trailing } = defaultThrottleConfig) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let sendValue = null;\n let throttled = null;\n let isComplete = false;\n const endThrottling = () => {\n throttled === null || throttled === void 0 ? void 0 : throttled.unsubscribe();\n throttled = null;\n if (trailing) {\n send();\n isComplete && subscriber.complete();\n }\n };\n const cleanupThrottling = () => {\n throttled = null;\n isComplete && subscriber.complete();\n };\n const startThrottle = (value) => (throttled = innerFrom(durationSelector(value)).subscribe(new OperatorSubscriber(subscriber, endThrottling, undefined, cleanupThrottling)));\n const send = () => {\n if (hasValue) {\n subscriber.next(sendValue);\n !isComplete && startThrottle(sendValue);\n }\n hasValue = false;\n sendValue = null;\n };\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n sendValue = value;\n !(throttled && !throttled.closed) && (leading ? send() : startThrottle(value));\n }, undefined, () => {\n isComplete = true;\n !(trailing && hasValue && throttled && !throttled.closed) && subscriber.complete();\n }));\n });\n}\n//# sourceMappingURL=throttle.js.map","import { switchMap } from './switchMap';\nexport function switchMapTo(innerObservable, resultSelector) {\n return resultSelector ? switchMap(() => innerObservable, resultSelector) : switchMap(() => innerObservable);\n}\n//# sourceMappingURL=switchMapTo.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function observeOn(scheduler, delay = 0) {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, (value) => subscriber.add(scheduler.schedule(() => subscriber.next(value), delay)), (err) => subscriber.add(scheduler.schedule(() => subscriber.error(err), delay)), () => subscriber.add(scheduler.schedule(() => subscriber.complete(), delay))));\n });\n}\n//# sourceMappingURL=observeOn.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nimport { identity } from '../util/identity';\nimport { noop } from '../util/noop';\nimport { popResultSelector } from '../util/args';\nexport function withLatestFrom(...inputs) {\n const project = popResultSelector(inputs);\n return operate((source, subscriber) => {\n const len = inputs.length;\n const otherValues = new Array(len);\n let hasValue = inputs.map(() => false);\n let ready = false;\n for (let i = 0; i < len; i++) {\n innerFrom(inputs[i]).subscribe(new OperatorSubscriber(subscriber, (value) => {\n otherValues[i] = value;\n if (!ready && !hasValue[i]) {\n hasValue[i] = true;\n (ready = hasValue.every(identity)) && (hasValue = null);\n }\n }, undefined, noop));\n }\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n if (ready) {\n const values = [value, ...otherValues];\n subscriber.next(project ? project(...values) : values);\n }\n }));\n });\n}\n//# sourceMappingURL=withLatestFrom.js.map","import { operate } from '../util/lift';\nimport { noop } from '../util/noop';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function sample(notifier) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let lastValue = null;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n lastValue = value;\n }));\n const emit = () => {\n if (hasValue) {\n hasValue = false;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n notifier.subscribe(new OperatorSubscriber(subscriber, emit, undefined, noop));\n });\n}\n//# sourceMappingURL=sample.js.map","import { filter } from './filter';\nexport function skip(count) {\n return filter((_, index) => count <= index);\n}\n//# sourceMappingURL=skip.js.map","import { innerFrom } from '../observable/from';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { operate } from '../util/lift';\nexport function catchError(selector) {\n return operate((source, subscriber) => {\n let innerSub = null;\n let syncUnsub = false;\n let handledResult;\n innerSub = source.subscribe(new OperatorSubscriber(subscriber, undefined, (err) => {\n handledResult = innerFrom(selector(err, catchError(selector)(source)));\n if (innerSub) {\n innerSub.unsubscribe();\n innerSub = null;\n handledResult.subscribe(subscriber);\n }\n else {\n syncUnsub = true;\n }\n }));\n if (syncUnsub) {\n innerSub.unsubscribe();\n innerSub = null;\n handledResult.subscribe(subscriber);\n }\n });\n}\n//# sourceMappingURL=catchError.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { arrRemove } from '../util/arrRemove';\nexport function bufferCount(bufferSize, startBufferEvery = null) {\n startBufferEvery = startBufferEvery !== null && startBufferEvery !== void 0 ? startBufferEvery : bufferSize;\n return operate((source, subscriber) => {\n let buffers = [];\n let count = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n let toEmit = null;\n if (count++ % startBufferEvery === 0) {\n buffers.push([]);\n }\n for (const buffer of buffers) {\n buffer.push(value);\n if (bufferSize <= buffer.length) {\n toEmit = toEmit !== null && toEmit !== void 0 ? toEmit : [];\n toEmit.push(buffer);\n }\n }\n if (toEmit) {\n for (const buffer of toEmit) {\n arrRemove(buffers, buffer);\n subscriber.next(buffer);\n }\n }\n }, undefined, () => {\n for (const buffer of buffers) {\n subscriber.next(buffer);\n }\n subscriber.complete();\n }, () => {\n buffers = null;\n }));\n });\n}\n//# sourceMappingURL=bufferCount.js.map","import { mergeMap } from './mergeMap';\nimport { isFunction } from '../util/isFunction';\nexport function concatMap(project, resultSelector) {\n return isFunction(resultSelector) ? mergeMap(project, resultSelector, 1) : mergeMap(project, 1);\n}\n//# sourceMappingURL=concatMap.js.map","import { defer } from './defer';\nexport function iif(condition, trueResult, falseResult) {\n return defer(() => (condition() ? trueResult : falseResult));\n}\n//# sourceMappingURL=iif.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function defaultIfEmpty(defaultValue = null) {\n return operate((source, subscriber) => {\n let hasValue = false;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n subscriber.next(value);\n }, undefined, () => {\n if (!hasValue) {\n subscriber.next(defaultValue);\n }\n subscriber.complete();\n }));\n });\n}\n//# sourceMappingURL=defaultIfEmpty.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function refCount() {\n return operate((source, subscriber) => {\n let connection = null;\n source._refCount++;\n const refCounter = new OperatorSubscriber(subscriber, undefined, undefined, undefined, () => {\n if (!source || source._refCount <= 0 || 0 < --source._refCount) {\n connection = null;\n return;\n }\n const sharedConnection = source._connection;\n const conn = connection;\n connection = null;\n if (sharedConnection && (!conn || sharedConnection === conn)) {\n sharedConnection.unsubscribe();\n }\n subscriber.unsubscribe();\n });\n source.subscribe(refCounter);\n if (!refCounter.closed) {\n connection = source.connect();\n }\n });\n}\n//# sourceMappingURL=refCount.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nimport { refCount as higherOrderRefCount } from '../operators/refCount';\nimport { OperatorSubscriber } from '../operators/OperatorSubscriber';\nexport class ConnectableObservable extends Observable {\n constructor(source, subjectFactory) {\n super();\n this.source = source;\n this.subjectFactory = subjectFactory;\n this._subject = null;\n this._refCount = 0;\n this._connection = null;\n }\n _subscribe(subscriber) {\n return this.getSubject().subscribe(subscriber);\n }\n getSubject() {\n const subject = this._subject;\n if (!subject || subject.isStopped) {\n this._subject = this.subjectFactory();\n }\n return this._subject;\n }\n _teardown() {\n this._refCount = 0;\n const { _connection } = this;\n this._subject = this._connection = null;\n _connection === null || _connection === void 0 ? void 0 : _connection.unsubscribe();\n }\n connect() {\n let connection = this._connection;\n if (!connection) {\n connection = this._connection = new Subscription();\n const subject = this.getSubject();\n connection.add(this.source.subscribe(new OperatorSubscriber(subject, undefined, (err) => {\n this._teardown();\n subject.error(err);\n }, () => {\n this._teardown();\n subject.complete();\n }, () => this._teardown())));\n if (connection.closed) {\n this._connection = null;\n connection = Subscription.EMPTY;\n }\n }\n return connection;\n }\n refCount() {\n return higherOrderRefCount()(this);\n }\n}\n//# sourceMappingURL=ConnectableObservable.js.map","import { multicast } from './multicast';\nimport { refCount } from './refCount';\nimport { Subject } from '../Subject';\nfunction shareSubjectFactory() {\n return new Subject();\n}\nexport function share() {\n return (source) => refCount()(multicast(shareSubjectFactory)(source));\n}\n//# sourceMappingURL=share.js.map","import { ConnectableObservable } from '../observable/ConnectableObservable';\nimport { hasLift, operate } from '../util/lift';\nimport { isFunction } from '../util/isFunction';\nexport function multicast(subjectOrSubjectFactory, selector) {\n const subjectFactory = isFunction(subjectOrSubjectFactory) ? subjectOrSubjectFactory : () => subjectOrSubjectFactory;\n if (isFunction(selector)) {\n return operate((source, subscriber) => {\n const subject = subjectFactory();\n selector(subject).subscribe(subscriber).add(source.subscribe(subject));\n });\n }\n return (source) => {\n const connectable = new ConnectableObservable(source, subjectFactory);\n if (hasLift(source)) {\n connectable.lift = source.lift;\n }\n connectable.source = source;\n connectable.subjectFactory = subjectFactory;\n return connectable;\n };\n}\n//# sourceMappingURL=multicast.js.map","import { Subscription } from '../Subscription';\nexport const animationFrameProvider = {\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel === null || cancel === void 0 ? void 0 : cancel(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.requestAnimationFrame) || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.cancelAnimationFrame) || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=animationFrameProvider.js.map","import { AsyncAction } from './AsyncAction';\nimport { animationFrameProvider } from './animationFrameProvider';\nexport class AnimationFrameAction extends AsyncAction {\n constructor(scheduler, work) {\n super(scheduler, work);\n this.scheduler = scheduler;\n this.work = work;\n }\n requestAsyncId(scheduler, id, delay = 0) {\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n scheduler.actions.push(this);\n return scheduler.scheduled || (scheduler.scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n recycleAsyncId(scheduler, id, delay = 0) {\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n if (scheduler.actions.length === 0) {\n animationFrameProvider.cancelAnimationFrame(id);\n scheduler.scheduled = undefined;\n }\n return undefined;\n }\n}\n//# sourceMappingURL=AnimationFrameAction.js.map","import { AsyncScheduler } from './AsyncScheduler';\nexport class AnimationFrameScheduler extends AsyncScheduler {\n flush(action) {\n this.active = true;\n this.scheduled = undefined;\n const { actions } = this;\n let error;\n let index = -1;\n action = action || actions.shift();\n const count = actions.length;\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (++index < count && (action = actions.shift()));\n this.active = false;\n if (error) {\n while (++index < count && (action = actions.shift())) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=AnimationFrameScheduler.js.map","import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\nexport const animationFrame = animationFrameScheduler;\n//# sourceMappingURL=animationFrame.js.map","import { concat } from '../observable/concat';\nimport { take } from './take';\nimport { ignoreElements } from './ignoreElements';\nimport { mapTo } from './mapTo';\nimport { mergeMap } from './mergeMap';\nexport function delayWhen(delayDurationSelector, subscriptionDelay) {\n if (subscriptionDelay) {\n return (source) => concat(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));\n }\n return mergeMap((value, index) => delayDurationSelector(value, index).pipe(take(1), mapTo(value)));\n}\n//# sourceMappingURL=delayWhen.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { noop } from '../util/noop';\nexport function ignoreElements() {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, noop));\n });\n}\n//# sourceMappingURL=ignoreElements.js.map","import { asyncScheduler } from '../scheduler/async';\nimport { delayWhen } from './delayWhen';\nimport { timer } from '../observable/timer';\nexport function delay(due, scheduler = asyncScheduler) {\n const duration = timer(due, scheduler);\n return delayWhen(() => duration);\n}\n//# sourceMappingURL=delay.js.map","const { isArray } = Array;\nconst { getPrototypeOf, prototype: objectProto, keys: getKeys } = Object;\nexport function argsArgArrayOrObject(args) {\n if (args.length === 1) {\n const first = args[0];\n if (isArray(first)) {\n return { args: first, keys: null };\n }\n if (isPOJO(first)) {\n const keys = getKeys(first);\n return {\n args: keys.map((key) => first[key]),\n keys,\n };\n }\n }\n return { args: args, keys: null };\n}\nfunction isPOJO(obj) {\n return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n}\n//# sourceMappingURL=argsArgArrayOrObject.js.map","import { Observable } from '../Observable';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject';\nimport { Subscriber } from '../Subscriber';\nimport { from } from './from';\nimport { identity } from '../util/identity';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { popResultSelector, popScheduler } from '../util/args';\nexport function combineLatest(...args) {\n const scheduler = popScheduler(args);\n const resultSelector = popResultSelector(args);\n const { args: observables, keys } = argsArgArrayOrObject(args);\n const result = new Observable(combineLatestInit(observables, scheduler, keys\n ?\n (values) => {\n const value = {};\n for (let i = 0; i < values.length; i++) {\n value[keys[i]] = values[i];\n }\n return value;\n }\n :\n identity));\n if (resultSelector) {\n return result.pipe(mapOneOrManyArgs(resultSelector));\n }\n return result;\n}\nclass CombineLatestSubscriber extends Subscriber {\n constructor(destination, _next, shouldComplete) {\n super(destination);\n this._next = _next;\n this.shouldComplete = shouldComplete;\n }\n _complete() {\n if (this.shouldComplete()) {\n super._complete();\n }\n else {\n this.unsubscribe();\n }\n }\n}\nexport function combineLatestInit(observables, scheduler, valueTransform = identity) {\n return (subscriber) => {\n const primarySubscribe = () => {\n const { length } = observables;\n const values = new Array(length);\n let active = length;\n const hasValues = observables.map(() => false);\n let waitingForFirstValues = true;\n const emit = () => subscriber.next(valueTransform(values.slice()));\n for (let i = 0; i < length; i++) {\n const subscribe = () => {\n const source = from(observables[i], scheduler);\n source.subscribe(new CombineLatestSubscriber(subscriber, (value) => {\n values[i] = value;\n if (waitingForFirstValues) {\n hasValues[i] = true;\n waitingForFirstValues = !hasValues.every(identity);\n }\n if (!waitingForFirstValues) {\n emit();\n }\n }, () => --active === 0));\n };\n maybeSchedule(scheduler, subscribe, subscriber);\n }\n };\n maybeSchedule(scheduler, primarySubscribe, subscriber);\n };\n}\nfunction maybeSchedule(scheduler, execute, subscription) {\n if (scheduler) {\n subscription.add(scheduler.schedule(execute));\n }\n else {\n execute();\n }\n}\n//# sourceMappingURL=combineLatest.js.map","import { OperatorSubscriber } from './OperatorSubscriber';\nexport function scanInternals(accumulator, seed, hasSeed, emitOnNext, emitBeforeComplete) {\n return (source, subscriber) => {\n let hasState = hasSeed;\n let state = seed;\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n const i = index++;\n state = hasState\n ?\n accumulator(state, value, i)\n :\n ((hasState = true), value);\n emitOnNext && subscriber.next(state);\n }, undefined, emitBeforeComplete &&\n (() => {\n hasState && subscriber.next(state);\n subscriber.complete();\n })));\n };\n}\n//# sourceMappingURL=scanInternals.js.map","import { operate } from '../util/lift';\nimport { scanInternals } from './scanInternals';\nexport function scan(accumulator, seed) {\n return operate(scanInternals(accumulator, seed, arguments.length >= 2, true));\n}\n//# sourceMappingURL=scan.js.map","import { zip as zipStatic } from '../observable/zip';\nimport { operate } from '../util/lift';\nexport function zip(...sources) {\n return operate((source, subscriber) => {\n zipStatic(source, ...sources).subscribe(subscriber);\n });\n}\nexport function zipWith(...otherInputs) {\n return zip(...otherInputs);\n}\n//# sourceMappingURL=zipWith.js.map","import { Observable } from '../Observable';\nimport { innerFrom } from './from';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { EMPTY } from './empty';\nimport { OperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { popResultSelector } from '../util/args';\nexport function zip(...args) {\n const resultSelector = popResultSelector(args);\n const sources = argsOrArgArray(args);\n return sources.length\n ? new Observable((subscriber) => {\n let buffers = sources.map(() => []);\n let completed = sources.map(() => false);\n subscriber.add(() => {\n buffers = completed = null;\n });\n for (let sourceIndex = 0; !subscriber.closed && sourceIndex < sources.length; sourceIndex++) {\n innerFrom(sources[sourceIndex]).subscribe(new OperatorSubscriber(subscriber, (value) => {\n buffers[sourceIndex].push(value);\n if (buffers.every((buffer) => buffer.length)) {\n const result = buffers.map((buffer) => buffer.shift());\n subscriber.next(resultSelector ? resultSelector(...result) : result);\n if (buffers.some((buffer, i) => !buffer.length && completed[i])) {\n subscriber.complete();\n }\n }\n }, undefined, () => {\n completed[sourceIndex] = true;\n !buffers[sourceIndex].length && subscriber.complete();\n }));\n }\n return () => {\n buffers = completed = null;\n };\n })\n : EMPTY;\n}\n//# sourceMappingURL=zip.js.map","import { asyncScheduler } from '../scheduler/async';\nimport { debounce } from './debounce';\nimport { timer } from '../observable/timer';\nexport function debounceTime(dueTime, scheduler = asyncScheduler) {\n const duration = timer(dueTime, scheduler);\n return debounce(() => duration);\n}\n//# sourceMappingURL=debounceTime.js.map","import { operate } from '../util/lift';\nimport { noop } from '../util/noop';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nexport function debounce(durationSelector) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let lastValue = null;\n let durationSubscriber = null;\n const emit = () => {\n durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();\n durationSubscriber = null;\n if (hasValue) {\n hasValue = false;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();\n hasValue = true;\n lastValue = value;\n durationSubscriber = new OperatorSubscriber(subscriber, emit, undefined, noop);\n innerFrom(durationSelector(value)).subscribe(durationSubscriber);\n }, undefined, () => {\n emit();\n subscriber.complete();\n }, () => {\n lastValue = durationSubscriber = null;\n }));\n });\n}\n//# sourceMappingURL=debounce.js.map"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/assets/javascripts/worker/search.8c7e0a7e.min.js b/docs/assets/javascripts/worker/search.8c7e0a7e.min.js deleted file mode 100644 index 6c2e7b8..0000000 --- a/docs/assets/javascripts/worker/search.8c7e0a7e.min.js +++ /dev/null @@ -1,59 +0,0 @@ -!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=5)}([function(e,t,r){"use strict"; -/*! - * escape-html - * Copyright(c) 2012-2013 TJ Holowaychuk - * Copyright(c) 2015 Andreas Lubbe - * Copyright(c) 2015 Tiancheng "Timothy" Gu - * MIT Licensed - */var n=/["'&<>]/;e.exports=function(e){var t,r=""+e,i=n.exec(r);if(!i)return r;var s="",o=0,a=0;for(o=i.index;o0){var u=I.utils.clone(t)||{};u.position=[o,a],u.index=i.length,i.push(new I.Token(r.slice(o,s),u))}o=s+1}}return i},I.tokenizer.separator=/[\s\-]+/ -/*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - */,I.Pipeline=function(){this._stack=[]},I.Pipeline.registeredFunctions=Object.create(null),I.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&I.utils.warn("Overwriting existing registered function: "+t),e.label=t,I.Pipeline.registeredFunctions[e.label]=e},I.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||I.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},I.Pipeline.load=function(e){var t=new I.Pipeline;return e.forEach((function(e){var r=I.Pipeline.registeredFunctions[e];if(!r)throw new Error("Cannot load unregistered function: "+e);t.add(r)})),t},I.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach((function(e){I.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},I.Pipeline.prototype.after=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");r+=1,this._stack.splice(r,0,t)},I.Pipeline.prototype.before=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");this._stack.splice(r,0,t)},I.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},I.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=i),s!=e);)n=r-t,i=t+Math.floor(n/2),s=this.elements[2*i];return s==e||s>e?2*i:sa?l+=2:o==a&&(t+=r[u+1]*n[l+1],u+=2,l+=2);return t},I.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},I.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var s,o=i.str.charAt(0);o in i.node.edges?s=i.node.edges[o]:(s=new I.TokenSet,i.node.edges[o]=s),1==i.str.length&&(s.final=!0),n.push({node:s,editsRemaining:i.editsRemaining,str:i.str.slice(1)})}if(0!=i.editsRemaining){if("*"in i.node.edges)var a=i.node.edges["*"];else{a=new I.TokenSet;i.node.edges["*"]=a}if(0==i.str.length&&(a.final=!0),n.push({node:a,editsRemaining:i.editsRemaining-1,str:i.str}),i.str.length>1&&n.push({node:i.node,editsRemaining:i.editsRemaining-1,str:i.str.slice(1)}),1==i.str.length&&(i.node.final=!0),i.str.length>=1){if("*"in i.node.edges)var u=i.node.edges["*"];else{u=new I.TokenSet;i.node.edges["*"]=u}1==i.str.length&&(u.final=!0),n.push({node:u,editsRemaining:i.editsRemaining-1,str:i.str.slice(1)})}if(i.str.length>1){var l,c=i.str.charAt(0),h=i.str.charAt(1);h in i.node.edges?l=i.node.edges[h]:(l=new I.TokenSet,i.node.edges[h]=l),1==i.str.length&&(l.final=!0),n.push({node:l,editsRemaining:i.editsRemaining-1,str:c+i.str.slice(2)})}}}return r},I.TokenSet.fromString=function(e){for(var t=new I.TokenSet,r=t,n=0,i=e.length;n=e;t--){var r=this.uncheckedNodes[t],n=r.child.toString();n in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[n]:(r.child._str=n,this.minimizedNodes[n]=r.child),this.uncheckedNodes.pop()}} -/*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - */,I.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},I.Index.prototype.search=function(e){return this.query((function(t){new I.QueryParser(e,t).parse()}))},I.Index.prototype.query=function(e){for(var t=new I.Query(this.fields),r=Object.create(null),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=0;a1?1:e},I.Builder.prototype.k1=function(e){this._k1=e},I.Builder.prototype.add=function(e,t){var r=e[this._ref],n=Object.keys(this._fields);this._documents[r]=t||{},this.documentCount+=1;for(var i=0;i=this.length)return I.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},I.QueryLexer.prototype.width=function(){return this.pos-this.start},I.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},I.QueryLexer.prototype.backup=function(){this.pos-=1},I.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=I.QueryLexer.EOS&&this.backup()},I.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(I.QueryLexer.TERM)),e.ignore(),e.more())return I.QueryLexer.lexText},I.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.EDIT_DISTANCE),I.QueryLexer.lexText},I.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.BOOST),I.QueryLexer.lexText},I.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(I.QueryLexer.TERM)},I.QueryLexer.termSeparator=I.tokenizer.separator,I.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==I.QueryLexer.EOS)return I.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return I.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if(t.match(I.QueryLexer.termSeparator))return I.QueryLexer.lexTerm}else e.escapeCharacter()}},I.QueryParser=function(e,t){this.lexer=new I.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},I.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=I.QueryParser.parseClause;e;)e=e(this);return this.query},I.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},I.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},I.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},I.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case I.QueryLexer.PRESENCE:return I.QueryParser.parsePresence;case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(r+=" with value '"+t.str+"'"),new I.QueryParseError(r,t.start,t.end)}},I.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=I.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=I.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+t.str+"'";throw new I.QueryParseError(r,t.start,t.end)}var n=e.peekLexeme();if(null==n){r="expecting term or field, found nothing";throw new I.QueryParseError(r,t.start,t.end)}switch(n.type){case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:r="expecting term or field, found '"+n.type+"'";throw new I.QueryParseError(r,n.start,n.end)}}},I.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var r=e.query.allFields.map((function(e){return"'"+e+"'"})).join(", "),n="unrecognised field '"+t.str+"', possible fields: "+r;throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.fields=[t.str];var i=e.peekLexeme();if(null==i){n="expecting term, found nothing";throw new I.QueryParseError(n,t.start,t.end)}switch(i.type){case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:n="expecting term, found '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}}},I.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(null!=r)switch(r.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+r.type+"'";throw new I.QueryParseError(n,r.start,r.end)}else e.nextClause()}},I.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n="edit distance must be numeric";throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.editDistance=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:n="Unexpected lexeme type '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}else e.nextClause()}},I.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n="boost must be numeric";throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.boost=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:n="Unexpected lexeme type '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}else e.nextClause()}},void 0===(i="function"==typeof(n=function(){return I})?n.call(t,r,t,e):n)||(e.exports=i)}()},function(e,t,r){"use strict";(function(t){e.exports=function(){if("object"==typeof globalThis)return globalThis;var e;try{e=this||new Function("return this")()}catch(e){if("object"==typeof window)return window;if("object"==typeof self)return self;if(void 0!==t)return t}return e}()}).call(this,r(4))},function(e,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}e.exports=r},function(e,t,r){"use strict";r.r(t),r.d(t,"handler",(function(){return u}));function n(e,t,r,n){return new(r||(r=Promise))((function(i,s){function o(e){try{u(n.next(e))}catch(e){s(e)}}function a(e){try{u(n.throw(e))}catch(e){s(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(o,a)}u((n=n.apply(e,t||[])).next())}))}Object.create;Object.create;r(1);var i,s=r(0);class o{constructor({config:e,docs:t,pipeline:r,index:n}){this.documents=function(e){const t=new Map,r=new Set;for(const n of e){const[e,i]=n.location.split("#"),o=n.location,a=n.title,u=s(n.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(i){const i=t.get(e);r.has(i)?t.set(o,{location:o,title:a,text:u,parent:i}):(i.title=n.title,i.text=u,r.add(i))}else t.set(o,{location:o,title:a,text:u})}return t}(t),this.highlight=function(e){const t=new RegExp(e.separator,"img"),r=(e,t,r)=>`${t}${r}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();const i=new RegExp(`(^|${e.separator})(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(t,"|")})`,"img");return e=>e.replace(i,r).replace(/<\/mark>(\s+)]*>/gim,"$1")}}(e),lunr.tokenizer.separator=new RegExp(e.separator),this.index=void 0===n?lunr((function(){1===e.lang.length&&"en"!==e.lang[0]?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang));const n=function(e,t){const[r,n]=[new Set(e),new Set(t)];return[...new Set([...r].filter(e=>!n.has(e)))]}(["trimmer","stopWordFilter","stemmer"],r);for(const t of e.lang.map(e=>"en"===e?lunr:lunr[e]))for(const e of n)this.pipeline.remove(t[e]),this.searchPipeline.remove(t[e]);this.field("title",{boost:1e3}),this.field("text"),this.ref("location");for(const e of t)this.add(e)})):lunr.Index.load(n)}search(e){if(e)try{const t=this.highlight(e),r=function(e){const t=new lunr.Query(["title","text"]);return new lunr.QueryParser(e,t).parse(),t.clauses}(e).filter(e=>e.presence!==lunr.Query.presence.PROHIBITED);return[...this.index.search(e+"*").reduce((e,{ref:n,score:i,matchData:s})=>{const o=this.documents.get(n);if(void 0!==o){const{location:n,title:a,text:u,parent:l}=o,c=function(e,t){const r=new Set(e),n={};for(let e=0;ee);e.push({location:n,title:t(a),text:t(u),score:i*(1+h),terms:c})}return e},[]).sort((e,t)=>t.score-e.score).reduce((e,t)=>{const r=this.documents.get(t.location);if(void 0!==r){const n="parent"in r?r.parent.location:r.location;e.set(n,[...e.get(n)||[],t])}return e},new Map).values()]}catch(t){console.warn(`Invalid query: ${e} – see https://bit.ly/2s3ChXG`)}return[]}}let a;function u(e){return n(this,void 0,void 0,(function*(){switch(e.type){case i.SETUP:return yield function(e){return n(this,void 0,void 0,(function*(){let t="../lunr";if("undefined"!=typeof parent&&"IFrameWorker"in parent){const e=document.querySelector("script[src]"),[r]=e.src.split("/worker");t=t.replace("..",r)}const r=[];for(const n of e.lang)"ja"===n&&r.push(t+"/tinyseg.min.js"),"en"!==n&&r.push(`${t}/min/lunr.${n}.min.js`);e.lang.length>1&&r.push(t+"/min/lunr.multi.min.js"),r.length&&(yield importScripts(t+"/min/lunr.stemmer.support.min.js",...r))}))}(e.data.config),a=new o(e.data),{type:i.READY};case i.QUERY:return{type:i.RESULT,data:a?a.search(e.data):[]};default:throw new TypeError("Invalid message type")}}))}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(i||(i={})),addEventListener("message",e=>n(void 0,void 0,void 0,(function*(){postMessage(yield u(e.data))})))}]); -//# sourceMappingURL=search.8c7e0a7e.min.js.map \ No newline at end of file diff --git a/docs/assets/javascripts/worker/search.8c7e0a7e.min.js.map b/docs/assets/javascripts/worker/search.8c7e0a7e.min.js.map deleted file mode 100644 index 85a2e5c..0000000 --- a/docs/assets/javascripts/worker/search.8c7e0a7e.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/escape-html/index.js","webpack:///./node_modules/lunr/lunr-exposed.js","webpack:///./node_modules/lunr/lunr.js","webpack:///./node_modules/expose-loader/dist/runtime/getGlobalThis.js","webpack:///(webpack)/buildin/global.js","webpack:///./node_modules/tslib/tslib.es6.js","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/_/index.ts","webpack:///./src/assets/javascripts/integrations/search/document/index.ts","webpack:///./src/assets/javascripts/integrations/search/highlighter/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/_/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/main/index.ts"],"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","matchHtmlRegExp","string","escape","str","match","exec","html","index","lastIndex","length","charCodeAt","substring","___EXPOSE_LOADER_IMPORT___","___EXPOSE_LOADER_GLOBAL_THIS___","global","step2list","step3list","v","C","re_mgr0","re_mgr1","re_meq1","re_s_v","re_1a","re2_1a","re_1b","re2_1b","re_1b_2","re2_1b_2","re3_1b_2","re4_1b_2","re_1c","re_2","re_3","re_4","re2_4","re_5","re_5_1","re3_5","porterStemmer","lunr","config","builder","Builder","pipeline","add","trimmer","stopWordFilter","stemmer","searchPipeline","build","version","utils","warn","this","message","console","asString","obj","toString","clone","keys","val","Array","isArray","slice","TypeError","FieldRef","docRef","fieldName","stringValue","_stringValue","joiner","fromString","indexOf","fieldRef","undefined","Set","elements","complete","intersect","other","union","contains","empty","a","b","intersection","element","push","concat","idf","posting","documentCount","documentsWithTerm","x","Math","log","abs","Token","metadata","update","fn","tokenizer","map","toLowerCase","len","tokens","sliceEnd","sliceStart","sliceLength","charAt","separator","tokenMetadata","Pipeline","_stack","registeredFunctions","registerFunction","label","warnIfFunctionNotRegistered","load","serialised","forEach","fnName","Error","fns","arguments","after","existingFn","newFn","pos","splice","before","remove","run","stackLength","memo","j","result","k","runString","token","reset","toJSON","Vector","_magnitude","positionForIndex","start","end","pivotPoint","floor","pivotIndex","insert","insertIdx","upsert","position","magnitude","sumOfSquares","elementsLength","sqrt","dot","otherVector","dotProduct","aLen","bLen","aVal","bVal","similarity","toArray","output","RegExp","w","stem","suffix","firstch","re","re2","re3","re4","substr","toUpperCase","test","replace","fp","generateStopWordFilter","stopWords","words","reduce","stopWord","TokenSet","final","edges","id","_nextId","fromArray","arr","finish","root","fromClause","clause","fromFuzzyString","term","editDistance","stack","node","editsRemaining","frame","pop","noEditNode","char","insertionNode","substitutionNode","transposeNode","charA","charB","next","prefix","edge","_str","labels","sort","qNode","qEdges","qLen","nEdges","nLen","q","qEdge","nEdge","previousWord","uncheckedNodes","minimizedNodes","word","commonPrefix","minimize","child","nextNode","parent","downTo","childKey","Index","attrs","invertedIndex","fieldVectors","tokenSet","fields","search","queryString","query","QueryParser","parse","Query","matchingFields","queryVectors","termFieldCache","requiredMatches","prohibitedMatches","clauses","terms","clauseMatches","usePipeline","termTokenSet","expandedTerms","presence","REQUIRED","field","expandedTerm","termIndex","_index","fieldPosting","matchingDocumentRefs","termField","matchingDocumentsSet","PROHIBITED","boost","fieldMatch","matchingDocumentRef","matchingFieldRef","MatchData","allRequiredMatches","allProhibitedMatches","matchingFieldRefs","results","matches","isNegated","docMatch","fieldVector","score","matchData","combine","ref","serializedIndex","serializedVectors","serializedInvertedIndex","tokenSetBuilder","tuple","_ref","_fields","_documents","fieldTermFrequencies","fieldLengths","_b","_k1","metadataWhitelist","attributes","RangeError","number","k1","doc","extractor","fieldTerms","metadataKey","calculateAverageFieldLengths","fieldRefs","numberOfFields","accumulator","documentsWithField","averageFieldLength","createFieldVectors","fieldRefsLength","termIdfCache","fieldLength","termFrequencies","termsLength","fieldBoost","docBoost","scoreWithPrecision","tf","round","createTokenSet","use","args","unshift","apply","clonedMetadata","metadataKeys","otherMatchData","allFields","wildcard","String","NONE","LEADING","TRAILING","OPTIONAL","options","QueryParseError","QueryLexer","lexemes","escapeCharPositions","state","lexText","sliceString","subSlices","join","emit","type","escapeCharacter","EOS","width","ignore","backup","acceptDigitRun","charCode","more","FIELD","TERM","EDIT_DISTANCE","BOOST","PRESENCE","lexField","lexer","lexTerm","lexEditDistance","lexBoost","lexEOS","termSeparator","currentClause","lexemeIdx","parseClause","peekLexeme","consumeLexeme","lexeme","nextClause","completedClause","parser","parsePresence","parseField","parseTerm","errorMessage","nextLexeme","possibleFields","f","parseEditDistance","parseBoost","parseInt","isNaN","globalThis","g","Function","e","window","self","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","rejected","done","then","SearchMessageType","docs","documents","Map","parents","path","hash","location","split","title","text","has","set","setupSearchDocumentMap","highlight","_","data","trim","setupSearchHighlighter","lang","multiLanguage","y","filter","difference","language","parseSearchQuery","document","startsWith","delete","getSearchQueryTerms","values","every","handler","SETUP","base","worker","querySelector","src","scripts","importScripts","setupSearchLanguages","READY","QUERY","RESULT","addEventListener","ev","postMessage"],"mappings":"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,IACN,IAEH,OAAO,SAAUK,GACf,GAAIA,GAAS6C,EAAM7C,EAAMlF,cAAgBkF,EAAMlF,WAAY,OAAOkF,IAiBtErG,EAAKO,eAAiBP,EAAKgJ,uBAAuB,CAChD,IACA,OACA,QACA,SACA,QACA,MACA,SACA,OACA,KACA,QACA,KACA,MACA,MACA,MACA,KACA,KACA,KACA,UACA,OACA,MACA,KACA,MACA,SACA,QACA,OACA,MACA,KACA,OACA,SACA,OACA,OACA,QACA,MACA,OACA,MACA,MACA,MACA,MACA,OACA,KACA,MACA,OACA,MACA,MACA,MACA,UACA,IACA,KACA,KACA,OACA,KACA,KACA,MACA,OACA,QACA,MACA,OACA,SACA,MACA,KACA,QACA,OACA,OACA,KACA,UACA,KACA,MACA,MACA,KACA,MACA,QACA,KACA,OACA,KACA,QACA,MACA,MACA,SACA,OACA,MACA,OACA,MACA,SACA,QACA,KACA,OACA,OACA,OACA,MACA,QACA,OACA,OACA,QACA,QACA,OACA,OACA,MACA,KACA,MACA,OACA,KACA,QACA,MACA,KACA,OACA,OACA,OACA,QACA,QACA,QACA,MACA,OACA,MACA,OACA,OACA,QACA,MACA,MACA,SAGFhJ,EAAK0E,SAASG,iBAAiB7E,EAAKO,eAAgB;;;;IAqBpDP,EAAKM,QAAU,SAAU+F,GACvB,OAAOA,EAAMxC,QAAO,SAAUtG,GAC5B,OAAOA,EAAEuL,QAAQ,OAAQ,IAAIA,QAAQ,OAAQ,QAIjD9I,EAAK0E,SAASG,iBAAiB7E,EAAKM,QAAS;;;;IA2B7CN,EAAKqJ,SAAW,WACdvI,KAAKwI,OAAQ,EACbxI,KAAKyI,MAAQ,GACbzI,KAAK0I,GAAKxJ,EAAKqJ,SAASI,QACxBzJ,EAAKqJ,SAASI,SAAW,GAW3BzJ,EAAKqJ,SAASI,QAAU,EASxBzJ,EAAKqJ,SAASK,UAAY,SAAUC,GAGlC,IAFA,IAAIzJ,EAAU,IAAIF,EAAKqJ,SAASlJ,QAEvB3E,EAAI,EAAG0I,EAAMyF,EAAI1L,OAAQzC,EAAI0I,EAAK1I,IACzC0E,EAAQ8G,OAAO2C,E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","file":"assets/javascripts/worker/search.8c7e0a7e.min.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 = 5);\n","/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n","var ___EXPOSE_LOADER_IMPORT___ = require(\"-!./lunr.js\");\nvar ___EXPOSE_LOADER_GET_GLOBAL_THIS___ = require(\"../expose-loader/dist/runtime/getGlobalThis.js\");\nvar ___EXPOSE_LOADER_GLOBAL_THIS___ = ___EXPOSE_LOADER_GET_GLOBAL_THIS___;\nif (typeof ___EXPOSE_LOADER_GLOBAL_THIS___[\"lunr\"] === 'undefined') ___EXPOSE_LOADER_GLOBAL_THIS___[\"lunr\"] = ___EXPOSE_LOADER_IMPORT___;\nmodule.exports = ___EXPOSE_LOADER_IMPORT___;\n","/**\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9\n * Copyright (C) 2020 Oliver Nightingale\n * @license MIT\n */\n\n;(function(){\n\n/**\n * A convenience function for configuring and constructing\n * a new lunr Index.\n *\n * A lunr.Builder instance is created and the pipeline setup\n * with a trimmer, stop word filter and stemmer.\n *\n * This builder object is yielded to the configuration function\n * that is passed as a parameter, allowing the list of fields\n * and other builder parameters to be customised.\n *\n * All documents _must_ be added within the passed config function.\n *\n * @example\n * var idx = lunr(function () {\n * this.field('title')\n * this.field('body')\n * this.ref('id')\n *\n * documents.forEach(function (doc) {\n * this.add(doc)\n * }, this)\n * })\n *\n * @see {@link lunr.Builder}\n * @see {@link lunr.Pipeline}\n * @see {@link lunr.trimmer}\n * @see {@link lunr.stopWordFilter}\n * @see {@link lunr.stemmer}\n * @namespace {function} lunr\n */\nvar lunr = function (config) {\n var builder = new lunr.Builder\n\n builder.pipeline.add(\n lunr.trimmer,\n lunr.stopWordFilter,\n lunr.stemmer\n )\n\n builder.searchPipeline.add(\n lunr.stemmer\n )\n\n config.call(builder, builder)\n return builder.build()\n}\n\nlunr.version = \"2.3.9\"\n/*!\n * lunr.utils\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A namespace containing utils for the rest of the lunr library\n * @namespace lunr.utils\n */\nlunr.utils = {}\n\n/**\n * Print a warning message to the console.\n *\n * @param {String} message The message to be printed.\n * @memberOf lunr.utils\n * @function\n */\nlunr.utils.warn = (function (global) {\n /* eslint-disable no-console */\n return function (message) {\n if (global.console && console.warn) {\n console.warn(message)\n }\n }\n /* eslint-enable no-console */\n})(this)\n\n/**\n * Convert an object to a string.\n *\n * In the case of `null` and `undefined` the function returns\n * the empty string, in all other cases the result of calling\n * `toString` on the passed object is returned.\n *\n * @param {Any} obj The object to convert to a string.\n * @return {String} string representation of the passed object.\n * @memberOf lunr.utils\n */\nlunr.utils.asString = function (obj) {\n if (obj === void 0 || obj === null) {\n return \"\"\n } else {\n return obj.toString()\n }\n}\n\n/**\n * Clones an object.\n *\n * Will create a copy of an existing object such that any mutations\n * on the copy cannot affect the original.\n *\n * Only shallow objects are supported, passing a nested object to this\n * function will cause a TypeError.\n *\n * Objects with primitives, and arrays of primitives are supported.\n *\n * @param {Object} obj The object to clone.\n * @return {Object} a clone of the passed object.\n * @throws {TypeError} when a nested object is passed.\n * @memberOf Utils\n */\nlunr.utils.clone = function (obj) {\n if (obj === null || obj === undefined) {\n return obj\n }\n\n var clone = Object.create(null),\n keys = Object.keys(obj)\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i],\n val = obj[key]\n\n if (Array.isArray(val)) {\n clone[key] = val.slice()\n continue\n }\n\n if (typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean') {\n clone[key] = val\n continue\n }\n\n throw new TypeError(\"clone is not deep and does not support nested objects\")\n }\n\n return clone\n}\nlunr.FieldRef = function (docRef, fieldName, stringValue) {\n this.docRef = docRef\n this.fieldName = fieldName\n this._stringValue = stringValue\n}\n\nlunr.FieldRef.joiner = \"/\"\n\nlunr.FieldRef.fromString = function (s) {\n var n = s.indexOf(lunr.FieldRef.joiner)\n\n if (n === -1) {\n throw \"malformed field ref string\"\n }\n\n var fieldRef = s.slice(0, n),\n docRef = s.slice(n + 1)\n\n return new lunr.FieldRef (docRef, fieldRef, s)\n}\n\nlunr.FieldRef.prototype.toString = function () {\n if (this._stringValue == undefined) {\n this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef\n }\n\n return this._stringValue\n}\n/*!\n * lunr.Set\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A lunr set.\n *\n * @constructor\n */\nlunr.Set = function (elements) {\n this.elements = Object.create(null)\n\n if (elements) {\n this.length = elements.length\n\n for (var i = 0; i < this.length; i++) {\n this.elements[elements[i]] = true\n }\n } else {\n this.length = 0\n }\n}\n\n/**\n * A complete set that contains all elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.complete = {\n intersect: function (other) {\n return other\n },\n\n union: function () {\n return this\n },\n\n contains: function () {\n return true\n }\n}\n\n/**\n * An empty set that contains no elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.empty = {\n intersect: function () {\n return this\n },\n\n union: function (other) {\n return other\n },\n\n contains: function () {\n return false\n }\n}\n\n/**\n * Returns true if this set contains the specified object.\n *\n * @param {object} object - Object whose presence in this set is to be tested.\n * @returns {boolean} - True if this set contains the specified object.\n */\nlunr.Set.prototype.contains = function (object) {\n return !!this.elements[object]\n}\n\n/**\n * Returns a new set containing only the elements that are present in both\n * this set and the specified set.\n *\n * @param {lunr.Set} other - set to intersect with this set.\n * @returns {lunr.Set} a new set that is the intersection of this and the specified set.\n */\n\nlunr.Set.prototype.intersect = function (other) {\n var a, b, elements, intersection = []\n\n if (other === lunr.Set.complete) {\n return this\n }\n\n if (other === lunr.Set.empty) {\n return other\n }\n\n if (this.length < other.length) {\n a = this\n b = other\n } else {\n a = other\n b = this\n }\n\n elements = Object.keys(a.elements)\n\n for (var i = 0; i < elements.length; i++) {\n var element = elements[i]\n if (element in b.elements) {\n intersection.push(element)\n }\n }\n\n return new lunr.Set (intersection)\n}\n\n/**\n * Returns a new set combining the elements of this and the specified set.\n *\n * @param {lunr.Set} other - set to union with this set.\n * @return {lunr.Set} a new set that is the union of this and the specified set.\n */\n\nlunr.Set.prototype.union = function (other) {\n if (other === lunr.Set.complete) {\n return lunr.Set.complete\n }\n\n if (other === lunr.Set.empty) {\n return this\n }\n\n return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))\n}\n/**\n * A function to calculate the inverse document frequency for\n * a posting. This is shared between the builder and the index\n *\n * @private\n * @param {object} posting - The posting for a given term\n * @param {number} documentCount - The total number of documents.\n */\nlunr.idf = function (posting, documentCount) {\n var documentsWithTerm = 0\n\n for (var fieldName in posting) {\n if (fieldName == '_index') continue // Ignore the term index, its not a field\n documentsWithTerm += Object.keys(posting[fieldName]).length\n }\n\n var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5)\n\n return Math.log(1 + Math.abs(x))\n}\n\n/**\n * A token wraps a string representation of a token\n * as it is passed through the text processing pipeline.\n *\n * @constructor\n * @param {string} [str=''] - The string token being wrapped.\n * @param {object} [metadata={}] - Metadata associated with this token.\n */\nlunr.Token = function (str, metadata) {\n this.str = str || \"\"\n this.metadata = metadata || {}\n}\n\n/**\n * Returns the token string that is being wrapped by this object.\n *\n * @returns {string}\n */\nlunr.Token.prototype.toString = function () {\n return this.str\n}\n\n/**\n * A token update function is used when updating or optionally\n * when cloning a token.\n *\n * @callback lunr.Token~updateFunction\n * @param {string} str - The string representation of the token.\n * @param {Object} metadata - All metadata associated with this token.\n */\n\n/**\n * Applies the given function to the wrapped string token.\n *\n * @example\n * token.update(function (str, metadata) {\n * return str.toUpperCase()\n * })\n *\n * @param {lunr.Token~updateFunction} fn - A function to apply to the token string.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.update = function (fn) {\n this.str = fn(this.str, this.metadata)\n return this\n}\n\n/**\n * Creates a clone of this token. Optionally a function can be\n * applied to the cloned token.\n *\n * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.clone = function (fn) {\n fn = fn || function (s) { return s }\n return new lunr.Token (fn(this.str, this.metadata), this.metadata)\n}\n/*!\n * lunr.tokenizer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A function for splitting a string into tokens ready to be inserted into\n * the search index. Uses `lunr.tokenizer.separator` to split strings, change\n * the value of this property to change how strings are split into tokens.\n *\n * This tokenizer will convert its parameter to a string by calling `toString` and\n * then will split this string on the character in `lunr.tokenizer.separator`.\n * Arrays will have their elements converted to strings and wrapped in a lunr.Token.\n *\n * Optional metadata can be passed to the tokenizer, this metadata will be cloned and\n * added as metadata to every token that is created from the object to be tokenized.\n *\n * @static\n * @param {?(string|object|object[])} obj - The object to convert into tokens\n * @param {?object} metadata - Optional metadata to associate with every token\n * @returns {lunr.Token[]}\n * @see {@link lunr.Pipeline}\n */\nlunr.tokenizer = function (obj, metadata) {\n if (obj == null || obj == undefined) {\n return []\n }\n\n if (Array.isArray(obj)) {\n return obj.map(function (t) {\n return new lunr.Token(\n lunr.utils.asString(t).toLowerCase(),\n lunr.utils.clone(metadata)\n )\n })\n }\n\n var str = obj.toString().toLowerCase(),\n len = str.length,\n tokens = []\n\n for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {\n var char = str.charAt(sliceEnd),\n sliceLength = sliceEnd - sliceStart\n\n if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {\n\n if (sliceLength > 0) {\n var tokenMetadata = lunr.utils.clone(metadata) || {}\n tokenMetadata[\"position\"] = [sliceStart, sliceLength]\n tokenMetadata[\"index\"] = tokens.length\n\n tokens.push(\n new lunr.Token (\n str.slice(sliceStart, sliceEnd),\n tokenMetadata\n )\n )\n }\n\n sliceStart = sliceEnd + 1\n }\n\n }\n\n return tokens\n}\n\n/**\n * The separator used to split a string into tokens. Override this property to change the behaviour of\n * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.\n *\n * @static\n * @see lunr.tokenizer\n */\nlunr.tokenizer.separator = /[\\s\\-]+/\n/*!\n * lunr.Pipeline\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Pipelines maintain an ordered list of functions to be applied to all\n * tokens in documents entering the search index and queries being ran against\n * the index.\n *\n * An instance of lunr.Index created with the lunr shortcut will contain a\n * pipeline with a stop word filter and an English language stemmer. Extra\n * functions can be added before or after either of these functions or these\n * default functions can be removed.\n *\n * When run the pipeline will call each function in turn, passing a token, the\n * index of that token in the original list of all tokens and finally a list of\n * all the original tokens.\n *\n * The output of functions in the pipeline will be passed to the next function\n * in the pipeline. To exclude a token from entering the index the function\n * should return undefined, the rest of the pipeline will not be called with\n * this token.\n *\n * For serialisation of pipelines to work, all functions used in an instance of\n * a pipeline should be registered with lunr.Pipeline. Registered functions can\n * then be loaded. If trying to load a serialised pipeline that uses functions\n * that are not registered an error will be thrown.\n *\n * If not planning on serialising the pipeline then registering pipeline functions\n * is not necessary.\n *\n * @constructor\n */\nlunr.Pipeline = function () {\n this._stack = []\n}\n\nlunr.Pipeline.registeredFunctions = Object.create(null)\n\n/**\n * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token\n * string as well as all known metadata. A pipeline function can mutate the token string\n * or mutate (or add) metadata for a given token.\n *\n * A pipeline function can indicate that the passed token should be discarded by returning\n * null, undefined or an empty string. This token will not be passed to any downstream pipeline\n * functions and will not be added to the index.\n *\n * Multiple tokens can be returned by returning an array of tokens. Each token will be passed\n * to any downstream pipeline functions and all will returned tokens will be added to the index.\n *\n * Any number of pipeline functions may be chained together using a lunr.Pipeline.\n *\n * @interface lunr.PipelineFunction\n * @param {lunr.Token} token - A token from the document being processed.\n * @param {number} i - The index of this token in the complete list of tokens for this document/field.\n * @param {lunr.Token[]} tokens - All tokens for this document/field.\n * @returns {(?lunr.Token|lunr.Token[])}\n */\n\n/**\n * Register a function with the pipeline.\n *\n * Functions that are used in the pipeline should be registered if the pipeline\n * needs to be serialised, or a serialised pipeline needs to be loaded.\n *\n * Registering a function does not add it to a pipeline, functions must still be\n * added to instances of the pipeline for them to be used when running a pipeline.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @param {String} label - The label to register this function with\n */\nlunr.Pipeline.registerFunction = function (fn, label) {\n if (label in this.registeredFunctions) {\n lunr.utils.warn('Overwriting existing registered function: ' + label)\n }\n\n fn.label = label\n lunr.Pipeline.registeredFunctions[fn.label] = fn\n}\n\n/**\n * Warns if the function is not registered as a Pipeline function.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @private\n */\nlunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {\n var isRegistered = fn.label && (fn.label in this.registeredFunctions)\n\n if (!isRegistered) {\n lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\\n', fn)\n }\n}\n\n/**\n * Loads a previously serialised pipeline.\n *\n * All functions to be loaded must already be registered with lunr.Pipeline.\n * If any function from the serialised data has not been registered then an\n * error will be thrown.\n *\n * @param {Object} serialised - The serialised pipeline to load.\n * @returns {lunr.Pipeline}\n */\nlunr.Pipeline.load = function (serialised) {\n var pipeline = new lunr.Pipeline\n\n serialised.forEach(function (fnName) {\n var fn = lunr.Pipeline.registeredFunctions[fnName]\n\n if (fn) {\n pipeline.add(fn)\n } else {\n throw new Error('Cannot load unregistered function: ' + fnName)\n }\n })\n\n return pipeline\n}\n\n/**\n * Adds new functions to the end of the pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline.\n */\nlunr.Pipeline.prototype.add = function () {\n var fns = Array.prototype.slice.call(arguments)\n\n fns.forEach(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n this._stack.push(fn)\n }, this)\n}\n\n/**\n * Adds a single function after a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.after = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n pos = pos + 1\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Adds a single function before a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.before = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Removes a function from the pipeline.\n *\n * @param {lunr.PipelineFunction} fn The function to remove from the pipeline.\n */\nlunr.Pipeline.prototype.remove = function (fn) {\n var pos = this._stack.indexOf(fn)\n if (pos == -1) {\n return\n }\n\n this._stack.splice(pos, 1)\n}\n\n/**\n * Runs the current list of functions that make up the pipeline against the\n * passed tokens.\n *\n * @param {Array} tokens The tokens to run through the pipeline.\n * @returns {Array}\n */\nlunr.Pipeline.prototype.run = function (tokens) {\n var stackLength = this._stack.length\n\n for (var i = 0; i < stackLength; i++) {\n var fn = this._stack[i]\n var memo = []\n\n for (var j = 0; j < tokens.length; j++) {\n var result = fn(tokens[j], j, tokens)\n\n if (result === null || result === void 0 || result === '') continue\n\n if (Array.isArray(result)) {\n for (var k = 0; k < result.length; k++) {\n memo.push(result[k])\n }\n } else {\n memo.push(result)\n }\n }\n\n tokens = memo\n }\n\n return tokens\n}\n\n/**\n * Convenience method for passing a string through a pipeline and getting\n * strings out. This method takes care of wrapping the passed string in a\n * token and mapping the resulting tokens back to strings.\n *\n * @param {string} str - The string to pass through the pipeline.\n * @param {?object} metadata - Optional metadata to associate with the token\n * passed to the pipeline.\n * @returns {string[]}\n */\nlunr.Pipeline.prototype.runString = function (str, metadata) {\n var token = new lunr.Token (str, metadata)\n\n return this.run([token]).map(function (t) {\n return t.toString()\n })\n}\n\n/**\n * Resets the pipeline by removing any existing processors.\n *\n */\nlunr.Pipeline.prototype.reset = function () {\n this._stack = []\n}\n\n/**\n * Returns a representation of the pipeline ready for serialisation.\n *\n * Logs a warning if the function has not been registered.\n *\n * @returns {Array}\n */\nlunr.Pipeline.prototype.toJSON = function () {\n return this._stack.map(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n\n return fn.label\n })\n}\n/*!\n * lunr.Vector\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A vector is used to construct the vector space of documents and queries. These\n * vectors support operations to determine the similarity between two documents or\n * a document and a query.\n *\n * Normally no parameters are required for initializing a vector, but in the case of\n * loading a previously dumped vector the raw elements can be provided to the constructor.\n *\n * For performance reasons vectors are implemented with a flat array, where an elements\n * index is immediately followed by its value. E.g. [index, value, index, value]. This\n * allows the underlying array to be as sparse as possible and still offer decent\n * performance when being used for vector calculations.\n *\n * @constructor\n * @param {Number[]} [elements] - The flat list of element index and element value pairs.\n */\nlunr.Vector = function (elements) {\n this._magnitude = 0\n this.elements = elements || []\n}\n\n\n/**\n * Calculates the position within the vector to insert a given index.\n *\n * This is used internally by insert and upsert. If there are duplicate indexes then\n * the position is returned as if the value for that index were to be updated, but it\n * is the callers responsibility to check whether there is a duplicate at that index\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @returns {Number}\n */\nlunr.Vector.prototype.positionForIndex = function (index) {\n // For an empty vector the tuple can be inserted at the beginning\n if (this.elements.length == 0) {\n return 0\n }\n\n var start = 0,\n end = this.elements.length / 2,\n sliceLength = end - start,\n pivotPoint = Math.floor(sliceLength / 2),\n pivotIndex = this.elements[pivotPoint * 2]\n\n while (sliceLength > 1) {\n if (pivotIndex < index) {\n start = pivotPoint\n }\n\n if (pivotIndex > index) {\n end = pivotPoint\n }\n\n if (pivotIndex == index) {\n break\n }\n\n sliceLength = end - start\n pivotPoint = start + Math.floor(sliceLength / 2)\n pivotIndex = this.elements[pivotPoint * 2]\n }\n\n if (pivotIndex == index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex > index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex < index) {\n return (pivotPoint + 1) * 2\n }\n}\n\n/**\n * Inserts an element at an index within the vector.\n *\n * Does not allow duplicates, will throw an error if there is already an entry\n * for this index.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n */\nlunr.Vector.prototype.insert = function (insertIdx, val) {\n this.upsert(insertIdx, val, function () {\n throw \"duplicate index\"\n })\n}\n\n/**\n * Inserts or updates an existing index within the vector.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n * @param {function} fn - A function that is called for updates, the existing value and the\n * requested value are passed as arguments\n */\nlunr.Vector.prototype.upsert = function (insertIdx, val, fn) {\n this._magnitude = 0\n var position = this.positionForIndex(insertIdx)\n\n if (this.elements[position] == insertIdx) {\n this.elements[position + 1] = fn(this.elements[position + 1], val)\n } else {\n this.elements.splice(position, 0, insertIdx, val)\n }\n}\n\n/**\n * Calculates the magnitude of this vector.\n *\n * @returns {Number}\n */\nlunr.Vector.prototype.magnitude = function () {\n if (this._magnitude) return this._magnitude\n\n var sumOfSquares = 0,\n elementsLength = this.elements.length\n\n for (var i = 1; i < elementsLength; i += 2) {\n var val = this.elements[i]\n sumOfSquares += val * val\n }\n\n return this._magnitude = Math.sqrt(sumOfSquares)\n}\n\n/**\n * Calculates the dot product of this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The vector to compute the dot product with.\n * @returns {Number}\n */\nlunr.Vector.prototype.dot = function (otherVector) {\n var dotProduct = 0,\n a = this.elements, b = otherVector.elements,\n aLen = a.length, bLen = b.length,\n aVal = 0, bVal = 0,\n i = 0, j = 0\n\n while (i < aLen && j < bLen) {\n aVal = a[i], bVal = b[j]\n if (aVal < bVal) {\n i += 2\n } else if (aVal > bVal) {\n j += 2\n } else if (aVal == bVal) {\n dotProduct += a[i + 1] * b[j + 1]\n i += 2\n j += 2\n }\n }\n\n return dotProduct\n}\n\n/**\n * Calculates the similarity between this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The other vector to calculate the\n * similarity with.\n * @returns {Number}\n */\nlunr.Vector.prototype.similarity = function (otherVector) {\n return this.dot(otherVector) / this.magnitude() || 0\n}\n\n/**\n * Converts the vector to an array of the elements within the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toArray = function () {\n var output = new Array (this.elements.length / 2)\n\n for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {\n output[j] = this.elements[i]\n }\n\n return output\n}\n\n/**\n * A JSON serializable representation of the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toJSON = function () {\n return this.elements\n}\n/* eslint-disable */\n/*!\n * lunr.stemmer\n * Copyright (C) 2020 Oliver Nightingale\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\n */\n\n/**\n * lunr.stemmer is an english language stemmer, this is a JavaScript\n * implementation of the PorterStemmer taken from http://tartarus.org/~martin\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token - The string to stem\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n * @function\n */\nlunr.stemmer = (function(){\n var step2list = {\n \"ational\" : \"ate\",\n \"tional\" : \"tion\",\n \"enci\" : \"ence\",\n \"anci\" : \"ance\",\n \"izer\" : \"ize\",\n \"bli\" : \"ble\",\n \"alli\" : \"al\",\n \"entli\" : \"ent\",\n \"eli\" : \"e\",\n \"ousli\" : \"ous\",\n \"ization\" : \"ize\",\n \"ation\" : \"ate\",\n \"ator\" : \"ate\",\n \"alism\" : \"al\",\n \"iveness\" : \"ive\",\n \"fulness\" : \"ful\",\n \"ousness\" : \"ous\",\n \"aliti\" : \"al\",\n \"iviti\" : \"ive\",\n \"biliti\" : \"ble\",\n \"logi\" : \"log\"\n },\n\n step3list = {\n \"icate\" : \"ic\",\n \"ative\" : \"\",\n \"alize\" : \"al\",\n \"iciti\" : \"ic\",\n \"ical\" : \"ic\",\n \"ful\" : \"\",\n \"ness\" : \"\"\n },\n\n c = \"[^aeiou]\", // consonant\n v = \"[aeiouy]\", // vowel\n C = c + \"[^aeiouy]*\", // consonant sequence\n V = v + \"[aeiou]*\", // vowel sequence\n\n mgr0 = \"^(\" + C + \")?\" + V + C, // [C]VC... is m>0\n meq1 = \"^(\" + C + \")?\" + V + C + \"(\" + V + \")?$\", // [C]VC[V] is m=1\n mgr1 = \"^(\" + C + \")?\" + V + C + V + C, // [C]VCVC... is m>1\n s_v = \"^(\" + C + \")?\" + v; // vowel in stem\n\n var re_mgr0 = new RegExp(mgr0);\n var re_mgr1 = new RegExp(mgr1);\n var re_meq1 = new RegExp(meq1);\n var re_s_v = new RegExp(s_v);\n\n var re_1a = /^(.+?)(ss|i)es$/;\n var re2_1a = /^(.+?)([^s])s$/;\n var re_1b = /^(.+?)eed$/;\n var re2_1b = /^(.+?)(ed|ing)$/;\n var re_1b_2 = /.$/;\n var re2_1b_2 = /(at|bl|iz)$/;\n var re3_1b_2 = new RegExp(\"([^aeiouylsz])\\\\1$\");\n var re4_1b_2 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var re_1c = /^(.+?[^aeiou])y$/;\n var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\n\n var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\n\n var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n var re2_4 = /^(.+?)(s|t)(ion)$/;\n\n var re_5 = /^(.+?)e$/;\n var re_5_1 = /ll$/;\n var re3_5 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var porterStemmer = function porterStemmer(w) {\n var stem,\n suffix,\n firstch,\n re,\n re2,\n re3,\n re4;\n\n if (w.length < 3) { return w; }\n\n firstch = w.substr(0,1);\n if (firstch == \"y\") {\n w = firstch.toUpperCase() + w.substr(1);\n }\n\n // Step 1a\n re = re_1a\n re2 = re2_1a;\n\n if (re.test(w)) { w = w.replace(re,\"$1$2\"); }\n else if (re2.test(w)) { w = w.replace(re2,\"$1$2\"); }\n\n // Step 1b\n re = re_1b;\n re2 = re2_1b;\n if (re.test(w)) {\n var fp = re.exec(w);\n re = re_mgr0;\n if (re.test(fp[1])) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1];\n re2 = re_s_v;\n if (re2.test(stem)) {\n w = stem;\n re2 = re2_1b_2;\n re3 = re3_1b_2;\n re4 = re4_1b_2;\n if (re2.test(w)) { w = w + \"e\"; }\n else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,\"\"); }\n else if (re4.test(w)) { w = w + \"e\"; }\n }\n }\n\n // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)\n re = re_1c;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n w = stem + \"i\";\n }\n\n // Step 2\n re = re_2;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step2list[suffix];\n }\n }\n\n // Step 3\n re = re_3;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step3list[suffix];\n }\n }\n\n // Step 4\n re = re_4;\n re2 = re2_4;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n if (re.test(stem)) {\n w = stem;\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1] + fp[2];\n re2 = re_mgr1;\n if (re2.test(stem)) {\n w = stem;\n }\n }\n\n // Step 5\n re = re_5;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n re2 = re_meq1;\n re3 = re3_5;\n if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {\n w = stem;\n }\n }\n\n re = re_5_1;\n re2 = re_mgr1;\n if (re.test(w) && re2.test(w)) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n\n // and turn initial Y back to y\n\n if (firstch == \"y\") {\n w = firstch.toLowerCase() + w.substr(1);\n }\n\n return w;\n };\n\n return function (token) {\n return token.update(porterStemmer);\n }\n})();\n\nlunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')\n/*!\n * lunr.stopWordFilter\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.generateStopWordFilter builds a stopWordFilter function from the provided\n * list of stop words.\n *\n * The built in lunr.stopWordFilter is built using this generator and can be used\n * to generate custom stopWordFilters for applications or non English languages.\n *\n * @function\n * @param {Array} token The token to pass through the filter\n * @returns {lunr.PipelineFunction}\n * @see lunr.Pipeline\n * @see lunr.stopWordFilter\n */\nlunr.generateStopWordFilter = function (stopWords) {\n var words = stopWords.reduce(function (memo, stopWord) {\n memo[stopWord] = stopWord\n return memo\n }, {})\n\n return function (token) {\n if (token && words[token.toString()] !== token.toString()) return token\n }\n}\n\n/**\n * lunr.stopWordFilter is an English language stop word list filter, any words\n * contained in the list will not be passed through the filter.\n *\n * This is intended to be used in the Pipeline. If the token does not pass the\n * filter then undefined will be returned.\n *\n * @function\n * @implements {lunr.PipelineFunction}\n * @params {lunr.Token} token - A token to check for being a stop word.\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n */\nlunr.stopWordFilter = lunr.generateStopWordFilter([\n 'a',\n 'able',\n 'about',\n 'across',\n 'after',\n 'all',\n 'almost',\n 'also',\n 'am',\n 'among',\n 'an',\n 'and',\n 'any',\n 'are',\n 'as',\n 'at',\n 'be',\n 'because',\n 'been',\n 'but',\n 'by',\n 'can',\n 'cannot',\n 'could',\n 'dear',\n 'did',\n 'do',\n 'does',\n 'either',\n 'else',\n 'ever',\n 'every',\n 'for',\n 'from',\n 'get',\n 'got',\n 'had',\n 'has',\n 'have',\n 'he',\n 'her',\n 'hers',\n 'him',\n 'his',\n 'how',\n 'however',\n 'i',\n 'if',\n 'in',\n 'into',\n 'is',\n 'it',\n 'its',\n 'just',\n 'least',\n 'let',\n 'like',\n 'likely',\n 'may',\n 'me',\n 'might',\n 'most',\n 'must',\n 'my',\n 'neither',\n 'no',\n 'nor',\n 'not',\n 'of',\n 'off',\n 'often',\n 'on',\n 'only',\n 'or',\n 'other',\n 'our',\n 'own',\n 'rather',\n 'said',\n 'say',\n 'says',\n 'she',\n 'should',\n 'since',\n 'so',\n 'some',\n 'than',\n 'that',\n 'the',\n 'their',\n 'them',\n 'then',\n 'there',\n 'these',\n 'they',\n 'this',\n 'tis',\n 'to',\n 'too',\n 'twas',\n 'us',\n 'wants',\n 'was',\n 'we',\n 'were',\n 'what',\n 'when',\n 'where',\n 'which',\n 'while',\n 'who',\n 'whom',\n 'why',\n 'will',\n 'with',\n 'would',\n 'yet',\n 'you',\n 'your'\n])\n\nlunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')\n/*!\n * lunr.trimmer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.trimmer is a pipeline function for trimming non word\n * characters from the beginning and end of tokens before they\n * enter the index.\n *\n * This implementation may not work correctly for non latin\n * characters and should either be removed or adapted for use\n * with languages with non-latin characters.\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token The token to pass through the filter\n * @returns {lunr.Token}\n * @see lunr.Pipeline\n */\nlunr.trimmer = function (token) {\n return token.update(function (s) {\n return s.replace(/^\\W+/, '').replace(/\\W+$/, '')\n })\n}\n\nlunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')\n/*!\n * lunr.TokenSet\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A token set is used to store the unique list of all tokens\n * within an index. Token sets are also used to represent an\n * incoming query to the index, this query token set and index\n * token set are then intersected to find which tokens to look\n * up in the inverted index.\n *\n * A token set can hold multiple tokens, as in the case of the\n * index token set, or it can hold a single token as in the\n * case of a simple query token set.\n *\n * Additionally token sets are used to perform wildcard matching.\n * Leading, contained and trailing wildcards are supported, and\n * from this edit distance matching can also be provided.\n *\n * Token sets are implemented as a minimal finite state automata,\n * where both common prefixes and suffixes are shared between tokens.\n * This helps to reduce the space used for storing the token set.\n *\n * @constructor\n */\nlunr.TokenSet = function () {\n this.final = false\n this.edges = {}\n this.id = lunr.TokenSet._nextId\n lunr.TokenSet._nextId += 1\n}\n\n/**\n * Keeps track of the next, auto increment, identifier to assign\n * to a new tokenSet.\n *\n * TokenSets require a unique identifier to be correctly minimised.\n *\n * @private\n */\nlunr.TokenSet._nextId = 1\n\n/**\n * Creates a TokenSet instance from the given sorted array of words.\n *\n * @param {String[]} arr - A sorted array of strings to create the set from.\n * @returns {lunr.TokenSet}\n * @throws Will throw an error if the input array is not sorted.\n */\nlunr.TokenSet.fromArray = function (arr) {\n var builder = new lunr.TokenSet.Builder\n\n for (var i = 0, len = arr.length; i < len; i++) {\n builder.insert(arr[i])\n }\n\n builder.finish()\n return builder.root\n}\n\n/**\n * Creates a token set from a query clause.\n *\n * @private\n * @param {Object} clause - A single clause from lunr.Query.\n * @param {string} clause.term - The query clause term.\n * @param {number} [clause.editDistance] - The optional edit distance for the term.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromClause = function (clause) {\n if ('editDistance' in clause) {\n return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance)\n } else {\n return lunr.TokenSet.fromString(clause.term)\n }\n}\n\n/**\n * Creates a token set representing a single string with a specified\n * edit distance.\n *\n * Insertions, deletions, substitutions and transpositions are each\n * treated as an edit distance of 1.\n *\n * Increasing the allowed edit distance will have a dramatic impact\n * on the performance of both creating and intersecting these TokenSets.\n * It is advised to keep the edit distance less than 3.\n *\n * @param {string} str - The string to create the token set from.\n * @param {number} editDistance - The allowed edit distance to match.\n * @returns {lunr.Vector}\n */\nlunr.TokenSet.fromFuzzyString = function (str, editDistance) {\n var root = new lunr.TokenSet\n\n var stack = [{\n node: root,\n editsRemaining: editDistance,\n str: str\n }]\n\n while (stack.length) {\n var frame = stack.pop()\n\n // no edit\n if (frame.str.length > 0) {\n var char = frame.str.charAt(0),\n noEditNode\n\n if (char in frame.node.edges) {\n noEditNode = frame.node.edges[char]\n } else {\n noEditNode = new lunr.TokenSet\n frame.node.edges[char] = noEditNode\n }\n\n if (frame.str.length == 1) {\n noEditNode.final = true\n }\n\n stack.push({\n node: noEditNode,\n editsRemaining: frame.editsRemaining,\n str: frame.str.slice(1)\n })\n }\n\n if (frame.editsRemaining == 0) {\n continue\n }\n\n // insertion\n if (\"*\" in frame.node.edges) {\n var insertionNode = frame.node.edges[\"*\"]\n } else {\n var insertionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = insertionNode\n }\n\n if (frame.str.length == 0) {\n insertionNode.final = true\n }\n\n stack.push({\n node: insertionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str\n })\n\n // deletion\n // can only do a deletion if we have enough edits remaining\n // and if there are characters left to delete in the string\n if (frame.str.length > 1) {\n stack.push({\n node: frame.node,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // deletion\n // just removing the last character from the str\n if (frame.str.length == 1) {\n frame.node.final = true\n }\n\n // substitution\n // can only do a substitution if we have enough edits remaining\n // and if there are characters left to substitute\n if (frame.str.length >= 1) {\n if (\"*\" in frame.node.edges) {\n var substitutionNode = frame.node.edges[\"*\"]\n } else {\n var substitutionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = substitutionNode\n }\n\n if (frame.str.length == 1) {\n substitutionNode.final = true\n }\n\n stack.push({\n node: substitutionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // transposition\n // can only do a transposition if there are edits remaining\n // and there are enough characters to transpose\n if (frame.str.length > 1) {\n var charA = frame.str.charAt(0),\n charB = frame.str.charAt(1),\n transposeNode\n\n if (charB in frame.node.edges) {\n transposeNode = frame.node.edges[charB]\n } else {\n transposeNode = new lunr.TokenSet\n frame.node.edges[charB] = transposeNode\n }\n\n if (frame.str.length == 1) {\n transposeNode.final = true\n }\n\n stack.push({\n node: transposeNode,\n editsRemaining: frame.editsRemaining - 1,\n str: charA + frame.str.slice(2)\n })\n }\n }\n\n return root\n}\n\n/**\n * Creates a TokenSet from a string.\n *\n * The string may contain one or more wildcard characters (*)\n * that will allow wildcard matching when intersecting with\n * another TokenSet.\n *\n * @param {string} str - The string to create a TokenSet from.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromString = function (str) {\n var node = new lunr.TokenSet,\n root = node\n\n /*\n * Iterates through all characters within the passed string\n * appending a node for each character.\n *\n * When a wildcard character is found then a self\n * referencing edge is introduced to continually match\n * any number of any characters.\n */\n for (var i = 0, len = str.length; i < len; i++) {\n var char = str[i],\n final = (i == len - 1)\n\n if (char == \"*\") {\n node.edges[char] = node\n node.final = final\n\n } else {\n var next = new lunr.TokenSet\n next.final = final\n\n node.edges[char] = next\n node = next\n }\n }\n\n return root\n}\n\n/**\n * Converts this TokenSet into an array of strings\n * contained within the TokenSet.\n *\n * This is not intended to be used on a TokenSet that\n * contains wildcards, in these cases the results are\n * undefined and are likely to cause an infinite loop.\n *\n * @returns {string[]}\n */\nlunr.TokenSet.prototype.toArray = function () {\n var words = []\n\n var stack = [{\n prefix: \"\",\n node: this\n }]\n\n while (stack.length) {\n var frame = stack.pop(),\n edges = Object.keys(frame.node.edges),\n len = edges.length\n\n if (frame.node.final) {\n /* In Safari, at this point the prefix is sometimes corrupted, see:\n * https://github.com/olivernn/lunr.js/issues/279 Calling any\n * String.prototype method forces Safari to \"cast\" this string to what\n * it's supposed to be, fixing the bug. */\n frame.prefix.charAt(0)\n words.push(frame.prefix)\n }\n\n for (var i = 0; i < len; i++) {\n var edge = edges[i]\n\n stack.push({\n prefix: frame.prefix.concat(edge),\n node: frame.node.edges[edge]\n })\n }\n }\n\n return words\n}\n\n/**\n * Generates a string representation of a TokenSet.\n *\n * This is intended to allow TokenSets to be used as keys\n * in objects, largely to aid the construction and minimisation\n * of a TokenSet. As such it is not designed to be a human\n * friendly representation of the TokenSet.\n *\n * @returns {string}\n */\nlunr.TokenSet.prototype.toString = function () {\n // NOTE: Using Object.keys here as this.edges is very likely\n // to enter 'hash-mode' with many keys being added\n //\n // avoiding a for-in loop here as it leads to the function\n // being de-optimised (at least in V8). From some simple\n // benchmarks the performance is comparable, but allowing\n // V8 to optimize may mean easy performance wins in the future.\n\n if (this._str) {\n return this._str\n }\n\n var str = this.final ? '1' : '0',\n labels = Object.keys(this.edges).sort(),\n len = labels.length\n\n for (var i = 0; i < len; i++) {\n var label = labels[i],\n node = this.edges[label]\n\n str = str + label + node.id\n }\n\n return str\n}\n\n/**\n * Returns a new TokenSet that is the intersection of\n * this TokenSet and the passed TokenSet.\n *\n * This intersection will take into account any wildcards\n * contained within the TokenSet.\n *\n * @param {lunr.TokenSet} b - An other TokenSet to intersect with.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.prototype.intersect = function (b) {\n var output = new lunr.TokenSet,\n frame = undefined\n\n var stack = [{\n qNode: b,\n output: output,\n node: this\n }]\n\n while (stack.length) {\n frame = stack.pop()\n\n // NOTE: As with the #toString method, we are using\n // Object.keys and a for loop instead of a for-in loop\n // as both of these objects enter 'hash' mode, causing\n // the function to be de-optimised in V8\n var qEdges = Object.keys(frame.qNode.edges),\n qLen = qEdges.length,\n nEdges = Object.keys(frame.node.edges),\n nLen = nEdges.length\n\n for (var q = 0; q < qLen; q++) {\n var qEdge = qEdges[q]\n\n for (var n = 0; n < nLen; n++) {\n var nEdge = nEdges[n]\n\n if (nEdge == qEdge || qEdge == '*') {\n var node = frame.node.edges[nEdge],\n qNode = frame.qNode.edges[qEdge],\n final = node.final && qNode.final,\n next = undefined\n\n if (nEdge in frame.output.edges) {\n // an edge already exists for this character\n // no need to create a new node, just set the finality\n // bit unless this node is already final\n next = frame.output.edges[nEdge]\n next.final = next.final || final\n\n } else {\n // no edge exists yet, must create one\n // set the finality bit and insert it\n // into the output\n next = new lunr.TokenSet\n next.final = final\n frame.output.edges[nEdge] = next\n }\n\n stack.push({\n qNode: qNode,\n output: next,\n node: node\n })\n }\n }\n }\n }\n\n return output\n}\nlunr.TokenSet.Builder = function () {\n this.previousWord = \"\"\n this.root = new lunr.TokenSet\n this.uncheckedNodes = []\n this.minimizedNodes = {}\n}\n\nlunr.TokenSet.Builder.prototype.insert = function (word) {\n var node,\n commonPrefix = 0\n\n if (word < this.previousWord) {\n throw new Error (\"Out of order word insertion\")\n }\n\n for (var i = 0; i < word.length && i < this.previousWord.length; i++) {\n if (word[i] != this.previousWord[i]) break\n commonPrefix++\n }\n\n this.minimize(commonPrefix)\n\n if (this.uncheckedNodes.length == 0) {\n node = this.root\n } else {\n node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child\n }\n\n for (var i = commonPrefix; i < word.length; i++) {\n var nextNode = new lunr.TokenSet,\n char = word[i]\n\n node.edges[char] = nextNode\n\n this.uncheckedNodes.push({\n parent: node,\n char: char,\n child: nextNode\n })\n\n node = nextNode\n }\n\n node.final = true\n this.previousWord = word\n}\n\nlunr.TokenSet.Builder.prototype.finish = function () {\n this.minimize(0)\n}\n\nlunr.TokenSet.Builder.prototype.minimize = function (downTo) {\n for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {\n var node = this.uncheckedNodes[i],\n childKey = node.child.toString()\n\n if (childKey in this.minimizedNodes) {\n node.parent.edges[node.char] = this.minimizedNodes[childKey]\n } else {\n // Cache the key for this node since\n // we know it can't change anymore\n node.child._str = childKey\n\n this.minimizedNodes[childKey] = node.child\n }\n\n this.uncheckedNodes.pop()\n }\n}\n/*!\n * lunr.Index\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * An index contains the built index of all documents and provides a query interface\n * to the index.\n *\n * Usually instances of lunr.Index will not be created using this constructor, instead\n * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be\n * used to load previously built and serialized indexes.\n *\n * @constructor\n * @param {Object} attrs - The attributes of the built search index.\n * @param {Object} attrs.invertedIndex - An index of term/field to document reference.\n * @param {Object} attrs.fieldVectors - Field vectors\n * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.\n * @param {string[]} attrs.fields - The names of indexed document fields.\n * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.\n */\nlunr.Index = function (attrs) {\n this.invertedIndex = attrs.invertedIndex\n this.fieldVectors = attrs.fieldVectors\n this.tokenSet = attrs.tokenSet\n this.fields = attrs.fields\n this.pipeline = attrs.pipeline\n}\n\n/**\n * A result contains details of a document matching a search query.\n * @typedef {Object} lunr.Index~Result\n * @property {string} ref - The reference of the document this result represents.\n * @property {number} score - A number between 0 and 1 representing how similar this document is to the query.\n * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match.\n */\n\n/**\n * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple\n * query language which itself is parsed into an instance of lunr.Query.\n *\n * For programmatically building queries it is advised to directly use lunr.Query, the query language\n * is best used for human entered text rather than program generated text.\n *\n * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported\n * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello'\n * or 'world', though those that contain both will rank higher in the results.\n *\n * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can\n * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding\n * wildcards will increase the number of documents that will be found but can also have a negative\n * impact on query performance, especially with wildcards at the beginning of a term.\n *\n * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term\n * hello in the title field will match this query. Using a field not present in the index will lead\n * to an error being thrown.\n *\n * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term\n * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported\n * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.\n * Avoid large values for edit distance to improve query performance.\n *\n * Each term also supports a presence modifier. By default a term's presence in document is optional, however\n * this can be changed to either required or prohibited. For a term's presence to be required in a document the\n * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and\n * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not\n * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.\n *\n * To escape special characters the backslash character '\\' can be used, this allows searches to include\n * characters that would normally be considered modifiers, e.g. `foo\\~2` will search for a term \"foo~2\" instead\n * of attempting to apply a boost of 2 to the search term \"foo\".\n *\n * @typedef {string} lunr.Index~QueryString\n * @example Simple single term query\n * hello\n * @example Multiple term query\n * hello world\n * @example term scoped to a field\n * title:hello\n * @example term with a boost of 10\n * hello^10\n * @example term with an edit distance of 2\n * hello~2\n * @example terms with presence modifiers\n * -foo +bar baz\n */\n\n/**\n * Performs a search against the index using lunr query syntax.\n *\n * Results will be returned sorted by their score, the most relevant results\n * will be returned first. For details on how the score is calculated, please see\n * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.\n *\n * For more programmatic querying use lunr.Index#query.\n *\n * @param {lunr.Index~QueryString} queryString - A string containing a lunr query.\n * @throws {lunr.QueryParseError} If the passed query string cannot be parsed.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.search = function (queryString) {\n return this.query(function (query) {\n var parser = new lunr.QueryParser(queryString, query)\n parser.parse()\n })\n}\n\n/**\n * A query builder callback provides a query object to be used to express\n * the query to perform on the index.\n *\n * @callback lunr.Index~queryBuilder\n * @param {lunr.Query} query - The query object to build up.\n * @this lunr.Query\n */\n\n/**\n * Performs a query against the index using the yielded lunr.Query object.\n *\n * If performing programmatic queries against the index, this method is preferred\n * over lunr.Index#search so as to avoid the additional query parsing overhead.\n *\n * A query object is yielded to the supplied function which should be used to\n * express the query to be run against the index.\n *\n * Note that although this function takes a callback parameter it is _not_ an\n * asynchronous operation, the callback is just yielded a query object to be\n * customized.\n *\n * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.query = function (fn) {\n // for each query clause\n // * process terms\n // * expand terms from token set\n // * find matching documents and metadata\n // * get document vectors\n // * score documents\n\n var query = new lunr.Query(this.fields),\n matchingFields = Object.create(null),\n queryVectors = Object.create(null),\n termFieldCache = Object.create(null),\n requiredMatches = Object.create(null),\n prohibitedMatches = Object.create(null)\n\n /*\n * To support field level boosts a query vector is created per\n * field. An empty vector is eagerly created to support negated\n * queries.\n */\n for (var i = 0; i < this.fields.length; i++) {\n queryVectors[this.fields[i]] = new lunr.Vector\n }\n\n fn.call(query, query)\n\n for (var i = 0; i < query.clauses.length; i++) {\n /*\n * Unless the pipeline has been disabled for this term, which is\n * the case for terms with wildcards, we need to pass the clause\n * term through the search pipeline. A pipeline returns an array\n * of processed terms. Pipeline functions may expand the passed\n * term, which means we may end up performing multiple index lookups\n * for a single query term.\n */\n var clause = query.clauses[i],\n terms = null,\n clauseMatches = lunr.Set.empty\n\n if (clause.usePipeline) {\n terms = this.pipeline.runString(clause.term, {\n fields: clause.fields\n })\n } else {\n terms = [clause.term]\n }\n\n for (var m = 0; m < terms.length; m++) {\n var term = terms[m]\n\n /*\n * Each term returned from the pipeline needs to use the same query\n * clause object, e.g. the same boost and or edit distance. The\n * simplest way to do this is to re-use the clause object but mutate\n * its term property.\n */\n clause.term = term\n\n /*\n * From the term in the clause we create a token set which will then\n * be used to intersect the indexes token set to get a list of terms\n * to lookup in the inverted index\n */\n var termTokenSet = lunr.TokenSet.fromClause(clause),\n expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()\n\n /*\n * If a term marked as required does not exist in the tokenSet it is\n * impossible for the search to return any matches. We set all the field\n * scoped required matches set to empty and stop examining any further\n * clauses.\n */\n if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = lunr.Set.empty\n }\n\n break\n }\n\n for (var j = 0; j < expandedTerms.length; j++) {\n /*\n * For each term get the posting and termIndex, this is required for\n * building the query vector.\n */\n var expandedTerm = expandedTerms[j],\n posting = this.invertedIndex[expandedTerm],\n termIndex = posting._index\n\n for (var k = 0; k < clause.fields.length; k++) {\n /*\n * For each field that this query term is scoped by (by default\n * all fields are in scope) we need to get all the document refs\n * that have this term in that field.\n *\n * The posting is the entry in the invertedIndex for the matching\n * term from above.\n */\n var field = clause.fields[k],\n fieldPosting = posting[field],\n matchingDocumentRefs = Object.keys(fieldPosting),\n termField = expandedTerm + \"/\" + field,\n matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)\n\n /*\n * if the presence of this term is required ensure that the matching\n * documents are added to the set of required matches for this clause.\n *\n */\n if (clause.presence == lunr.Query.presence.REQUIRED) {\n clauseMatches = clauseMatches.union(matchingDocumentsSet)\n\n if (requiredMatches[field] === undefined) {\n requiredMatches[field] = lunr.Set.complete\n }\n }\n\n /*\n * if the presence of this term is prohibited ensure that the matching\n * documents are added to the set of prohibited matches for this field,\n * creating that set if it does not yet exist.\n */\n if (clause.presence == lunr.Query.presence.PROHIBITED) {\n if (prohibitedMatches[field] === undefined) {\n prohibitedMatches[field] = lunr.Set.empty\n }\n\n prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)\n\n /*\n * Prohibited matches should not be part of the query vector used for\n * similarity scoring and no metadata should be extracted so we continue\n * to the next field\n */\n continue\n }\n\n /*\n * The query field vector is populated using the termIndex found for\n * the term and a unit value with the appropriate boost applied.\n * Using upsert because there could already be an entry in the vector\n * for the term we are working with. In that case we just add the scores\n * together.\n */\n queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })\n\n /**\n * If we've already seen this term, field combo then we've already collected\n * the matching documents and metadata, no need to go through all that again\n */\n if (termFieldCache[termField]) {\n continue\n }\n\n for (var l = 0; l < matchingDocumentRefs.length; l++) {\n /*\n * All metadata for this term/field/document triple\n * are then extracted and collected into an instance\n * of lunr.MatchData ready to be returned in the query\n * results\n */\n var matchingDocumentRef = matchingDocumentRefs[l],\n matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field),\n metadata = fieldPosting[matchingDocumentRef],\n fieldMatch\n\n if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) {\n matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata)\n } else {\n fieldMatch.add(expandedTerm, field, metadata)\n }\n\n }\n\n termFieldCache[termField] = true\n }\n }\n }\n\n /**\n * If the presence was required we need to update the requiredMatches field sets.\n * We do this after all fields for the term have collected their matches because\n * the clause terms presence is required in _any_ of the fields not _all_ of the\n * fields.\n */\n if (clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)\n }\n }\n }\n\n /**\n * Need to combine the field scoped required and prohibited\n * matching documents into a global set of required and prohibited\n * matches\n */\n var allRequiredMatches = lunr.Set.complete,\n allProhibitedMatches = lunr.Set.empty\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i]\n\n if (requiredMatches[field]) {\n allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])\n }\n\n if (prohibitedMatches[field]) {\n allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])\n }\n }\n\n var matchingFieldRefs = Object.keys(matchingFields),\n results = [],\n matches = Object.create(null)\n\n /*\n * If the query is negated (contains only prohibited terms)\n * we need to get _all_ fieldRefs currently existing in the\n * index. This is only done when we know that the query is\n * entirely prohibited terms to avoid any cost of getting all\n * fieldRefs unnecessarily.\n *\n * Additionally, blank MatchData must be created to correctly\n * populate the results.\n */\n if (query.isNegated()) {\n matchingFieldRefs = Object.keys(this.fieldVectors)\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n var matchingFieldRef = matchingFieldRefs[i]\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)\n matchingFields[matchingFieldRef] = new lunr.MatchData\n }\n }\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n /*\n * Currently we have document fields that match the query, but we\n * need to return documents. The matchData and scores are combined\n * from multiple fields belonging to the same document.\n *\n * Scores are calculated by field, using the query vectors created\n * above, and combined into a final document score using addition.\n */\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),\n docRef = fieldRef.docRef\n\n if (!allRequiredMatches.contains(docRef)) {\n continue\n }\n\n if (allProhibitedMatches.contains(docRef)) {\n continue\n }\n\n var fieldVector = this.fieldVectors[fieldRef],\n score = queryVectors[fieldRef.fieldName].similarity(fieldVector),\n docMatch\n\n if ((docMatch = matches[docRef]) !== undefined) {\n docMatch.score += score\n docMatch.matchData.combine(matchingFields[fieldRef])\n } else {\n var match = {\n ref: docRef,\n score: score,\n matchData: matchingFields[fieldRef]\n }\n matches[docRef] = match\n results.push(match)\n }\n }\n\n /*\n * Sort the results objects by score, highest first.\n */\n return results.sort(function (a, b) {\n return b.score - a.score\n })\n}\n\n/**\n * Prepares the index for JSON serialization.\n *\n * The schema for this JSON blob will be described in a\n * separate JSON schema file.\n *\n * @returns {Object}\n */\nlunr.Index.prototype.toJSON = function () {\n var invertedIndex = Object.keys(this.invertedIndex)\n .sort()\n .map(function (term) {\n return [term, this.invertedIndex[term]]\n }, this)\n\n var fieldVectors = Object.keys(this.fieldVectors)\n .map(function (ref) {\n return [ref, this.fieldVectors[ref].toJSON()]\n }, this)\n\n return {\n version: lunr.version,\n fields: this.fields,\n fieldVectors: fieldVectors,\n invertedIndex: invertedIndex,\n pipeline: this.pipeline.toJSON()\n }\n}\n\n/**\n * Loads a previously serialized lunr.Index\n *\n * @param {Object} serializedIndex - A previously serialized lunr.Index\n * @returns {lunr.Index}\n */\nlunr.Index.load = function (serializedIndex) {\n var attrs = {},\n fieldVectors = {},\n serializedVectors = serializedIndex.fieldVectors,\n invertedIndex = Object.create(null),\n serializedInvertedIndex = serializedIndex.invertedIndex,\n tokenSetBuilder = new lunr.TokenSet.Builder,\n pipeline = lunr.Pipeline.load(serializedIndex.pipeline)\n\n if (serializedIndex.version != lunr.version) {\n lunr.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr '\" + lunr.version + \"' does not match serialized index '\" + serializedIndex.version + \"'\")\n }\n\n for (var i = 0; i < serializedVectors.length; i++) {\n var tuple = serializedVectors[i],\n ref = tuple[0],\n elements = tuple[1]\n\n fieldVectors[ref] = new lunr.Vector(elements)\n }\n\n for (var i = 0; i < serializedInvertedIndex.length; i++) {\n var tuple = serializedInvertedIndex[i],\n term = tuple[0],\n posting = tuple[1]\n\n tokenSetBuilder.insert(term)\n invertedIndex[term] = posting\n }\n\n tokenSetBuilder.finish()\n\n attrs.fields = serializedIndex.fields\n\n attrs.fieldVectors = fieldVectors\n attrs.invertedIndex = invertedIndex\n attrs.tokenSet = tokenSetBuilder.root\n attrs.pipeline = pipeline\n\n return new lunr.Index(attrs)\n}\n/*!\n * lunr.Builder\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Builder performs indexing on a set of documents and\n * returns instances of lunr.Index ready for querying.\n *\n * All configuration of the index is done via the builder, the\n * fields to index, the document reference, the text processing\n * pipeline and document scoring parameters are all set on the\n * builder before indexing.\n *\n * @constructor\n * @property {string} _ref - Internal reference to the document reference field.\n * @property {string[]} _fields - Internal reference to the document fields to index.\n * @property {object} invertedIndex - The inverted index maps terms to document fields.\n * @property {object} documentTermFrequencies - Keeps track of document term frequencies.\n * @property {object} documentLengths - Keeps track of the length of documents added to the index.\n * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.\n * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.\n * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.\n * @property {number} documentCount - Keeps track of the total number of documents indexed.\n * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.\n * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.\n * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.\n * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.\n */\nlunr.Builder = function () {\n this._ref = \"id\"\n this._fields = Object.create(null)\n this._documents = Object.create(null)\n this.invertedIndex = Object.create(null)\n this.fieldTermFrequencies = {}\n this.fieldLengths = {}\n this.tokenizer = lunr.tokenizer\n this.pipeline = new lunr.Pipeline\n this.searchPipeline = new lunr.Pipeline\n this.documentCount = 0\n this._b = 0.75\n this._k1 = 1.2\n this.termIndex = 0\n this.metadataWhitelist = []\n}\n\n/**\n * Sets the document field used as the document reference. Every document must have this field.\n * The type of this field in the document should be a string, if it is not a string it will be\n * coerced into a string by calling toString.\n *\n * The default ref is 'id'.\n *\n * The ref should _not_ be changed during indexing, it should be set before any documents are\n * added to the index. Changing it during indexing can lead to inconsistent results.\n *\n * @param {string} ref - The name of the reference field in the document.\n */\nlunr.Builder.prototype.ref = function (ref) {\n this._ref = ref\n}\n\n/**\n * A function that is used to extract a field from a document.\n *\n * Lunr expects a field to be at the top level of a document, if however the field\n * is deeply nested within a document an extractor function can be used to extract\n * the right field for indexing.\n *\n * @callback fieldExtractor\n * @param {object} doc - The document being added to the index.\n * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.\n * @example Extracting a nested field\n * function (doc) { return doc.nested.field }\n */\n\n/**\n * Adds a field to the list of document fields that will be indexed. Every document being\n * indexed should have this field. Null values for this field in indexed documents will\n * not cause errors but will limit the chance of that document being retrieved by searches.\n *\n * All fields should be added before adding documents to the index. Adding fields after\n * a document has been indexed will have no effect on already indexed documents.\n *\n * Fields can be boosted at build time. This allows terms within that field to have more\n * importance when ranking search results. Use a field boost to specify that matches within\n * one field are more important than other fields.\n *\n * @param {string} fieldName - The name of a field to index in all documents.\n * @param {object} attributes - Optional attributes associated with this field.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.\n * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.\n * @throws {RangeError} fieldName cannot contain unsupported characters '/'\n */\nlunr.Builder.prototype.field = function (fieldName, attributes) {\n if (/\\//.test(fieldName)) {\n throw new RangeError (\"Field '\" + fieldName + \"' contains illegal character '/'\")\n }\n\n this._fields[fieldName] = attributes || {}\n}\n\n/**\n * A parameter to tune the amount of field length normalisation that is applied when\n * calculating relevance scores. A value of 0 will completely disable any normalisation\n * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b\n * will be clamped to the range 0 - 1.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.b = function (number) {\n if (number < 0) {\n this._b = 0\n } else if (number > 1) {\n this._b = 1\n } else {\n this._b = number\n }\n}\n\n/**\n * A parameter that controls the speed at which a rise in term frequency results in term\n * frequency saturation. The default value is 1.2. Setting this to a higher value will give\n * slower saturation levels, a lower value will result in quicker saturation.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.k1 = function (number) {\n this._k1 = number\n}\n\n/**\n * Adds a document to the index.\n *\n * Before adding fields to the index the index should have been fully setup, with the document\n * ref and all fields to index already having been specified.\n *\n * The document must have a field name as specified by the ref (by default this is 'id') and\n * it should have all fields defined for indexing, though null or undefined values will not\n * cause errors.\n *\n * Entire documents can be boosted at build time. Applying a boost to a document indicates that\n * this document should rank higher in search results than other documents.\n *\n * @param {object} doc - The document to add to the index.\n * @param {object} attributes - Optional attributes associated with this document.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.\n */\nlunr.Builder.prototype.add = function (doc, attributes) {\n var docRef = doc[this._ref],\n fields = Object.keys(this._fields)\n\n this._documents[docRef] = attributes || {}\n this.documentCount += 1\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i],\n extractor = this._fields[fieldName].extractor,\n field = extractor ? extractor(doc) : doc[fieldName],\n tokens = this.tokenizer(field, {\n fields: [fieldName]\n }),\n terms = this.pipeline.run(tokens),\n fieldRef = new lunr.FieldRef (docRef, fieldName),\n fieldTerms = Object.create(null)\n\n this.fieldTermFrequencies[fieldRef] = fieldTerms\n this.fieldLengths[fieldRef] = 0\n\n // store the length of this field for this document\n this.fieldLengths[fieldRef] += terms.length\n\n // calculate term frequencies for this field\n for (var j = 0; j < terms.length; j++) {\n var term = terms[j]\n\n if (fieldTerms[term] == undefined) {\n fieldTerms[term] = 0\n }\n\n fieldTerms[term] += 1\n\n // add to inverted index\n // create an initial posting if one doesn't exist\n if (this.invertedIndex[term] == undefined) {\n var posting = Object.create(null)\n posting[\"_index\"] = this.termIndex\n this.termIndex += 1\n\n for (var k = 0; k < fields.length; k++) {\n posting[fields[k]] = Object.create(null)\n }\n\n this.invertedIndex[term] = posting\n }\n\n // add an entry for this term/fieldName/docRef to the invertedIndex\n if (this.invertedIndex[term][fieldName][docRef] == undefined) {\n this.invertedIndex[term][fieldName][docRef] = Object.create(null)\n }\n\n // store all whitelisted metadata about this token in the\n // inverted index\n for (var l = 0; l < this.metadataWhitelist.length; l++) {\n var metadataKey = this.metadataWhitelist[l],\n metadata = term.metadata[metadataKey]\n\n if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) {\n this.invertedIndex[term][fieldName][docRef][metadataKey] = []\n }\n\n this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata)\n }\n }\n\n }\n}\n\n/**\n * Calculates the average document length for this index\n *\n * @private\n */\nlunr.Builder.prototype.calculateAverageFieldLengths = function () {\n\n var fieldRefs = Object.keys(this.fieldLengths),\n numberOfFields = fieldRefs.length,\n accumulator = {},\n documentsWithField = {}\n\n for (var i = 0; i < numberOfFields; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n field = fieldRef.fieldName\n\n documentsWithField[field] || (documentsWithField[field] = 0)\n documentsWithField[field] += 1\n\n accumulator[field] || (accumulator[field] = 0)\n accumulator[field] += this.fieldLengths[fieldRef]\n }\n\n var fields = Object.keys(this._fields)\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i]\n accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]\n }\n\n this.averageFieldLength = accumulator\n}\n\n/**\n * Builds a vector space model of every document using lunr.Vector\n *\n * @private\n */\nlunr.Builder.prototype.createFieldVectors = function () {\n var fieldVectors = {},\n fieldRefs = Object.keys(this.fieldTermFrequencies),\n fieldRefsLength = fieldRefs.length,\n termIdfCache = Object.create(null)\n\n for (var i = 0; i < fieldRefsLength; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n fieldName = fieldRef.fieldName,\n fieldLength = this.fieldLengths[fieldRef],\n fieldVector = new lunr.Vector,\n termFrequencies = this.fieldTermFrequencies[fieldRef],\n terms = Object.keys(termFrequencies),\n termsLength = terms.length\n\n\n var fieldBoost = this._fields[fieldName].boost || 1,\n docBoost = this._documents[fieldRef.docRef].boost || 1\n\n for (var j = 0; j < termsLength; j++) {\n var term = terms[j],\n tf = termFrequencies[term],\n termIndex = this.invertedIndex[term]._index,\n idf, score, scoreWithPrecision\n\n if (termIdfCache[term] === undefined) {\n idf = lunr.idf(this.invertedIndex[term], this.documentCount)\n termIdfCache[term] = idf\n } else {\n idf = termIdfCache[term]\n }\n\n score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)\n score *= fieldBoost\n score *= docBoost\n scoreWithPrecision = Math.round(score * 1000) / 1000\n // Converts 1.23456789 to 1.234.\n // Reducing the precision so that the vectors take up less\n // space when serialised. Doing it now so that they behave\n // the same before and after serialisation. Also, this is\n // the fastest approach to reducing a number's precision in\n // JavaScript.\n\n fieldVector.insert(termIndex, scoreWithPrecision)\n }\n\n fieldVectors[fieldRef] = fieldVector\n }\n\n this.fieldVectors = fieldVectors\n}\n\n/**\n * Creates a token set of all tokens in the index using lunr.TokenSet\n *\n * @private\n */\nlunr.Builder.prototype.createTokenSet = function () {\n this.tokenSet = lunr.TokenSet.fromArray(\n Object.keys(this.invertedIndex).sort()\n )\n}\n\n/**\n * Builds the index, creating an instance of lunr.Index.\n *\n * This completes the indexing process and should only be called\n * once all documents have been added to the index.\n *\n * @returns {lunr.Index}\n */\nlunr.Builder.prototype.build = function () {\n this.calculateAverageFieldLengths()\n this.createFieldVectors()\n this.createTokenSet()\n\n return new lunr.Index({\n invertedIndex: this.invertedIndex,\n fieldVectors: this.fieldVectors,\n tokenSet: this.tokenSet,\n fields: Object.keys(this._fields),\n pipeline: this.searchPipeline\n })\n}\n\n/**\n * Applies a plugin to the index builder.\n *\n * A plugin is a function that is called with the index builder as its context.\n * Plugins can be used to customise or extend the behaviour of the index\n * in some way. A plugin is just a function, that encapsulated the custom\n * behaviour that should be applied when building the index.\n *\n * The plugin function will be called with the index builder as its argument, additional\n * arguments can also be passed when calling use. The function will be called\n * with the index builder as its context.\n *\n * @param {Function} plugin The plugin to apply.\n */\nlunr.Builder.prototype.use = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1)\n args.unshift(this)\n fn.apply(this, args)\n}\n/**\n * Contains and collects metadata about a matching document.\n * A single instance of lunr.MatchData is returned as part of every\n * lunr.Index~Result.\n *\n * @constructor\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n * @property {object} metadata - A cloned collection of metadata associated with this document.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData = function (term, field, metadata) {\n var clonedMetadata = Object.create(null),\n metadataKeys = Object.keys(metadata || {})\n\n // Cloning the metadata to prevent the original\n // being mutated during match data combination.\n // Metadata is kept in an array within the inverted\n // index so cloning the data can be done with\n // Array#slice\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n clonedMetadata[key] = metadata[key].slice()\n }\n\n this.metadata = Object.create(null)\n\n if (term !== undefined) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = clonedMetadata\n }\n}\n\n/**\n * An instance of lunr.MatchData will be created for every term that matches a\n * document. However only one instance is required in a lunr.Index~Result. This\n * method combines metadata from another instance of lunr.MatchData with this\n * objects metadata.\n *\n * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData.prototype.combine = function (otherMatchData) {\n var terms = Object.keys(otherMatchData.metadata)\n\n for (var i = 0; i < terms.length; i++) {\n var term = terms[i],\n fields = Object.keys(otherMatchData.metadata[term])\n\n if (this.metadata[term] == undefined) {\n this.metadata[term] = Object.create(null)\n }\n\n for (var j = 0; j < fields.length; j++) {\n var field = fields[j],\n keys = Object.keys(otherMatchData.metadata[term][field])\n\n if (this.metadata[term][field] == undefined) {\n this.metadata[term][field] = Object.create(null)\n }\n\n for (var k = 0; k < keys.length; k++) {\n var key = keys[k]\n\n if (this.metadata[term][field][key] == undefined) {\n this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]\n } else {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])\n }\n\n }\n }\n }\n}\n\n/**\n * Add metadata for a term/field pair to this instance of match data.\n *\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n */\nlunr.MatchData.prototype.add = function (term, field, metadata) {\n if (!(term in this.metadata)) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = metadata\n return\n }\n\n if (!(field in this.metadata[term])) {\n this.metadata[term][field] = metadata\n return\n }\n\n var metadataKeys = Object.keys(metadata)\n\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n\n if (key in this.metadata[term][field]) {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])\n } else {\n this.metadata[term][field][key] = metadata[key]\n }\n }\n}\n/**\n * A lunr.Query provides a programmatic way of defining queries to be performed\n * against a {@link lunr.Index}.\n *\n * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method\n * so the query object is pre-initialized with the right index fields.\n *\n * @constructor\n * @property {lunr.Query~Clause[]} clauses - An array of query clauses.\n * @property {string[]} allFields - An array of all available fields in a lunr.Index.\n */\nlunr.Query = function (allFields) {\n this.clauses = []\n this.allFields = allFields\n}\n\n/**\n * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause.\n *\n * This allows wildcards to be added to the beginning and end of a term without having to manually do any string\n * concatenation.\n *\n * The wildcard constants can be bitwise combined to select both leading and trailing wildcards.\n *\n * @constant\n * @default\n * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour\n * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists\n * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with trailing wildcard\n * query.term('foo', { wildcard: lunr.Query.wildcard.TRAILING })\n * @example query term with leading and trailing wildcard\n * query.term('foo', {\n * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING\n * })\n */\n\nlunr.Query.wildcard = new String (\"*\")\nlunr.Query.wildcard.NONE = 0\nlunr.Query.wildcard.LEADING = 1\nlunr.Query.wildcard.TRAILING = 2\n\n/**\n * Constants for indicating what kind of presence a term must have in matching documents.\n *\n * @constant\n * @enum {number}\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with required presence\n * query.term('foo', { presence: lunr.Query.presence.REQUIRED })\n */\nlunr.Query.presence = {\n /**\n * Term's presence in a document is optional, this is the default value.\n */\n OPTIONAL: 1,\n\n /**\n * Term's presence in a document is required, documents that do not contain\n * this term will not be returned.\n */\n REQUIRED: 2,\n\n /**\n * Term's presence in a document is prohibited, documents that do contain\n * this term will not be returned.\n */\n PROHIBITED: 3\n}\n\n/**\n * A single clause in a {@link lunr.Query} contains a term and details on how to\n * match that term against a {@link lunr.Index}.\n *\n * @typedef {Object} lunr.Query~Clause\n * @property {string[]} fields - The fields in an index this clause should be matched against.\n * @property {number} [boost=1] - Any boost that should be applied when matching this clause.\n * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.\n * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.\n * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.\n * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.\n */\n\n/**\n * Adds a {@link lunr.Query~Clause} to this query.\n *\n * Unless the clause contains the fields to be matched all fields will be matched. In addition\n * a default boost of 1 is applied to the clause.\n *\n * @param {lunr.Query~Clause} clause - The clause to add to this query.\n * @see lunr.Query~Clause\n * @returns {lunr.Query}\n */\nlunr.Query.prototype.clause = function (clause) {\n if (!('fields' in clause)) {\n clause.fields = this.allFields\n }\n\n if (!('boost' in clause)) {\n clause.boost = 1\n }\n\n if (!('usePipeline' in clause)) {\n clause.usePipeline = true\n }\n\n if (!('wildcard' in clause)) {\n clause.wildcard = lunr.Query.wildcard.NONE\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) {\n clause.term = \"*\" + clause.term\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) {\n clause.term = \"\" + clause.term + \"*\"\n }\n\n if (!('presence' in clause)) {\n clause.presence = lunr.Query.presence.OPTIONAL\n }\n\n this.clauses.push(clause)\n\n return this\n}\n\n/**\n * A negated query is one in which every clause has a presence of\n * prohibited. These queries require some special processing to return\n * the expected results.\n *\n * @returns boolean\n */\nlunr.Query.prototype.isNegated = function () {\n for (var i = 0; i < this.clauses.length; i++) {\n if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}\n * to the list of clauses that make up this query.\n *\n * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion\n * to a token or token-like string should be done before calling this method.\n *\n * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an\n * array, each term in the array will share the same options.\n *\n * @param {object|object[]} term - The term(s) to add to the query.\n * @param {object} [options] - Any additional properties to add to the query clause.\n * @returns {lunr.Query}\n * @see lunr.Query#clause\n * @see lunr.Query~Clause\n * @example adding a single term to a query\n * query.term(\"foo\")\n * @example adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard\n * query.term(\"foo\", {\n * fields: [\"title\"],\n * boost: 10,\n * wildcard: lunr.Query.wildcard.TRAILING\n * })\n * @example using lunr.tokenizer to convert a string to tokens before using them as terms\n * query.term(lunr.tokenizer(\"foo bar\"))\n */\nlunr.Query.prototype.term = function (term, options) {\n if (Array.isArray(term)) {\n term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)\n return this\n }\n\n var clause = options || {}\n clause.term = term.toString()\n\n this.clause(clause)\n\n return this\n}\nlunr.QueryParseError = function (message, start, end) {\n this.name = \"QueryParseError\"\n this.message = message\n this.start = start\n this.end = end\n}\n\nlunr.QueryParseError.prototype = new Error\nlunr.QueryLexer = function (str) {\n this.lexemes = []\n this.str = str\n this.length = str.length\n this.pos = 0\n this.start = 0\n this.escapeCharPositions = []\n}\n\nlunr.QueryLexer.prototype.run = function () {\n var state = lunr.QueryLexer.lexText\n\n while (state) {\n state = state(this)\n }\n}\n\nlunr.QueryLexer.prototype.sliceString = function () {\n var subSlices = [],\n sliceStart = this.start,\n sliceEnd = this.pos\n\n for (var i = 0; i < this.escapeCharPositions.length; i++) {\n sliceEnd = this.escapeCharPositions[i]\n subSlices.push(this.str.slice(sliceStart, sliceEnd))\n sliceStart = sliceEnd + 1\n }\n\n subSlices.push(this.str.slice(sliceStart, this.pos))\n this.escapeCharPositions.length = 0\n\n return subSlices.join('')\n}\n\nlunr.QueryLexer.prototype.emit = function (type) {\n this.lexemes.push({\n type: type,\n str: this.sliceString(),\n start: this.start,\n end: this.pos\n })\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.escapeCharacter = function () {\n this.escapeCharPositions.push(this.pos - 1)\n this.pos += 1\n}\n\nlunr.QueryLexer.prototype.next = function () {\n if (this.pos >= this.length) {\n return lunr.QueryLexer.EOS\n }\n\n var char = this.str.charAt(this.pos)\n this.pos += 1\n return char\n}\n\nlunr.QueryLexer.prototype.width = function () {\n return this.pos - this.start\n}\n\nlunr.QueryLexer.prototype.ignore = function () {\n if (this.start == this.pos) {\n this.pos += 1\n }\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.backup = function () {\n this.pos -= 1\n}\n\nlunr.QueryLexer.prototype.acceptDigitRun = function () {\n var char, charCode\n\n do {\n char = this.next()\n charCode = char.charCodeAt(0)\n } while (charCode > 47 && charCode < 58)\n\n if (char != lunr.QueryLexer.EOS) {\n this.backup()\n }\n}\n\nlunr.QueryLexer.prototype.more = function () {\n return this.pos < this.length\n}\n\nlunr.QueryLexer.EOS = 'EOS'\nlunr.QueryLexer.FIELD = 'FIELD'\nlunr.QueryLexer.TERM = 'TERM'\nlunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'\nlunr.QueryLexer.BOOST = 'BOOST'\nlunr.QueryLexer.PRESENCE = 'PRESENCE'\n\nlunr.QueryLexer.lexField = function (lexer) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.FIELD)\n lexer.ignore()\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexTerm = function (lexer) {\n if (lexer.width() > 1) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.TERM)\n }\n\n lexer.ignore()\n\n if (lexer.more()) {\n return lunr.QueryLexer.lexText\n }\n}\n\nlunr.QueryLexer.lexEditDistance = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.EDIT_DISTANCE)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexBoost = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.BOOST)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexEOS = function (lexer) {\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n}\n\n// This matches the separator used when tokenising fields\n// within a document. These should match otherwise it is\n// not possible to search for some tokens within a document.\n//\n// It is possible for the user to change the separator on the\n// tokenizer so it _might_ clash with any other of the special\n// characters already used within the search string, e.g. :.\n//\n// This means that it is possible to change the separator in\n// such a way that makes some words unsearchable using a search\n// string.\nlunr.QueryLexer.termSeparator = lunr.tokenizer.separator\n\nlunr.QueryLexer.lexText = function (lexer) {\n while (true) {\n var char = lexer.next()\n\n if (char == lunr.QueryLexer.EOS) {\n return lunr.QueryLexer.lexEOS\n }\n\n // Escape character is '\\'\n if (char.charCodeAt(0) == 92) {\n lexer.escapeCharacter()\n continue\n }\n\n if (char == \":\") {\n return lunr.QueryLexer.lexField\n }\n\n if (char == \"~\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexEditDistance\n }\n\n if (char == \"^\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexBoost\n }\n\n // \"+\" indicates term presence is required\n // checking for length to ensure that only\n // leading \"+\" are considered\n if (char == \"+\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n // \"-\" indicates term presence is prohibited\n // checking for length to ensure that only\n // leading \"-\" are considered\n if (char == \"-\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n if (char.match(lunr.QueryLexer.termSeparator)) {\n return lunr.QueryLexer.lexTerm\n }\n }\n}\n\nlunr.QueryParser = function (str, query) {\n this.lexer = new lunr.QueryLexer (str)\n this.query = query\n this.currentClause = {}\n this.lexemeIdx = 0\n}\n\nlunr.QueryParser.prototype.parse = function () {\n this.lexer.run()\n this.lexemes = this.lexer.lexemes\n\n var state = lunr.QueryParser.parseClause\n\n while (state) {\n state = state(this)\n }\n\n return this.query\n}\n\nlunr.QueryParser.prototype.peekLexeme = function () {\n return this.lexemes[this.lexemeIdx]\n}\n\nlunr.QueryParser.prototype.consumeLexeme = function () {\n var lexeme = this.peekLexeme()\n this.lexemeIdx += 1\n return lexeme\n}\n\nlunr.QueryParser.prototype.nextClause = function () {\n var completedClause = this.currentClause\n this.query.clause(completedClause)\n this.currentClause = {}\n}\n\nlunr.QueryParser.parseClause = function (parser) {\n var lexeme = parser.peekLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.type) {\n case lunr.QueryLexer.PRESENCE:\n return lunr.QueryParser.parsePresence\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expected either a field or a term, found \" + lexeme.type\n\n if (lexeme.str.length >= 1) {\n errorMessage += \" with value '\" + lexeme.str + \"'\"\n }\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n}\n\nlunr.QueryParser.parsePresence = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.str) {\n case \"-\":\n parser.currentClause.presence = lunr.Query.presence.PROHIBITED\n break\n case \"+\":\n parser.currentClause.presence = lunr.Query.presence.REQUIRED\n break\n default:\n var errorMessage = \"unrecognised presence operator'\" + lexeme.str + \"'\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term or field, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term or field, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseField = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n if (parser.query.allFields.indexOf(lexeme.str) == -1) {\n var possibleFields = parser.query.allFields.map(function (f) { return \"'\" + f + \"'\" }).join(', '),\n errorMessage = \"unrecognised field '\" + lexeme.str + \"', possible fields: \" + possibleFields\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.fields = [lexeme.str]\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseTerm = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n parser.currentClause.term = lexeme.str.toLowerCase()\n\n if (lexeme.str.indexOf(\"*\") != -1) {\n parser.currentClause.usePipeline = false\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseEditDistance = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var editDistance = parseInt(lexeme.str, 10)\n\n if (isNaN(editDistance)) {\n var errorMessage = \"edit distance must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.editDistance = editDistance\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseBoost = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var boost = parseInt(lexeme.str, 10)\n\n if (isNaN(boost)) {\n var errorMessage = \"boost must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.boost = boost\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\n /**\n * export the module via AMD, CommonJS or as a browser global\n * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js\n */\n ;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory)\n } else if (typeof exports === 'object') {\n /**\n * Node. Does not work with strict CommonJS, but\n * only CommonJS-like enviroments that support module.exports,\n * like Node.\n */\n module.exports = factory()\n } else {\n // Browser globals (root is window)\n root.lunr = factory()\n }\n }(this, function () {\n /**\n * Just return a value to define the module export.\n * This example returns an object, but the module\n * can return a function as the exported value.\n */\n return lunr\n }))\n})();\n","\"use strict\";\n\n// eslint-disable-next-line func-names\nmodule.exports = function () {\n if (typeof globalThis === \"object\") {\n return globalThis;\n }\n\n var g;\n\n try {\n // This works if eval is allowed (see CSP)\n // eslint-disable-next-line no-new-func\n g = this || new Function(\"return this\")();\n } catch (e) {\n // This works if the window reference is available\n if (typeof window === \"object\") {\n return window;\n } // This works if the self reference is available\n\n\n if (typeof self === \"object\") {\n return self;\n } // This works if the global reference is available\n\n\n if (typeof global !== \"undefined\") {\n return global;\n }\n }\n\n return g;\n}();","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n SearchDocument,\n SearchDocumentMap,\n setupSearchDocumentMap\n} from \"../document\"\nimport {\n SearchHighlightFactoryFn,\n setupSearchHighlighter\n} from \"../highlighter\"\nimport {\n SearchQueryTerms,\n getSearchQueryTerms,\n parseSearchQuery\n} from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index configuration\n */\nexport interface SearchIndexConfig {\n lang: string[] /* Search languages */\n separator: string /* Search separator */\n}\n\n/**\n * Search index document\n */\nexport interface SearchIndexDocument {\n location: string /* Document location */\n title: string /* Document title */\n text: string /* Document text */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search index pipeline function\n */\nexport type SearchIndexPipelineFn =\n | \"trimmer\" /* Trimmer */\n | \"stopWordFilter\" /* Stop word filter */\n | \"stemmer\" /* Stemmer */\n\n/**\n * Search index pipeline\n */\nexport type SearchIndexPipeline = SearchIndexPipelineFn[]\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search index\n *\n * This interfaces describes the format of the `search_index.json` file which\n * is automatically built by the MkDocs search plugin.\n */\nexport interface SearchIndex {\n config: SearchIndexConfig /* Search index configuration */\n docs: SearchIndexDocument[] /* Search index documents */\n index?: object /* Prebuilt index */\n pipeline?: SearchIndexPipeline /* Search index pipeline */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search metadata\n */\nexport interface SearchMetadata {\n score: number /* Score (relevance) */\n terms: SearchQueryTerms /* Search query terms */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search result\n */\nexport type SearchResult = Array<\n SearchDocument & SearchMetadata\n> // tslint:disable-line\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute the difference of two lists of strings\n *\n * @param a - 1st list of strings\n * @param b - 2nd list of strings\n *\n * @return Difference\n */\nfunction difference(a: string[], b: string[]): string[] {\n const [x, y] = [new Set(a), new Set(b)]\n return [\n ...new Set([...x].filter(value => !y.has(value)))\n ]\n}\n\n/* ----------------------------------------------------------------------------\n * Class\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n *\n * Note that `lunr` is injected via Webpack, as it will otherwise also be\n * bundled in the application bundle.\n */\nexport class Search {\n\n /**\n * Search document mapping\n *\n * A mapping of URLs (including hash fragments) to the actual articles and\n * sections of the documentation. The search document mapping must be created\n * regardless of whether the index was prebuilt or not, as `lunr` itself will\n * only store the actual index.\n */\n protected documents: SearchDocumentMap\n\n /**\n * Search highlight factory function\n */\n protected highlight: SearchHighlightFactoryFn\n\n /**\n * The underlying `lunr` search index\n */\n protected index: lunr.Index\n\n /**\n * Create the search integration\n *\n * @param data - Search index\n */\n public constructor({ config, docs, pipeline, index }: SearchIndex) {\n this.documents = setupSearchDocumentMap(docs)\n this.highlight = setupSearchHighlighter(config)\n\n /* Set separator for tokenizer */\n lunr.tokenizer.separator = new RegExp(config.separator)\n\n /* If no index was given, create it */\n if (typeof index === \"undefined\") {\n this.index = lunr(function() {\n\n /* Set up multi-language support */\n if (config.lang.length === 1 && config.lang[0] !== \"en\") {\n this.use((lunr as any)[config.lang[0]])\n } else if (config.lang.length > 1) {\n this.use((lunr as any).multiLanguage(...config.lang))\n }\n\n /* Compute functions to be removed from the pipeline */\n const fns = difference([\n \"trimmer\", \"stopWordFilter\", \"stemmer\"\n ], pipeline!)\n\n /* Remove functions from the pipeline for registered languages */\n for (const lang of config.lang.map(language => (\n language === \"en\" ? lunr : (lunr as any)[language]\n ))) {\n for (const fn of fns) {\n this.pipeline.remove(lang[fn])\n this.searchPipeline.remove(lang[fn])\n }\n }\n\n /* Set up fields and reference */\n this.field(\"title\", { boost: 1000 })\n this.field(\"text\")\n this.ref(\"location\")\n\n /* Index documents */\n for (const doc of docs)\n this.add(doc)\n })\n\n /* Handle prebuilt index */\n } else {\n this.index = lunr.Index.load(index)\n }\n }\n\n /**\n * Search for matching documents\n *\n * The search index which MkDocs provides is divided up into articles, which\n * contain the whole content of the individual pages, and sections, which only\n * contain the contents of the subsections obtained by breaking the individual\n * pages up at `h1` ... `h6`. As there may be many sections on different pages\n * with identical titles (for example within this very project, e.g. \"Usage\"\n * or \"Installation\"), they need to be put into the context of the containing\n * page. For this reason, section results are grouped within their respective\n * articles which are the top-level results that are returned.\n *\n * @param query - Query value\n *\n * @return Search results\n */\n public search(query: string): SearchResult[] {\n if (query) {\n try {\n const highlight = this.highlight(query)\n\n /* Parse query to extract clauses for analysis */\n const clauses = parseSearchQuery(query)\n .filter(clause => (\n clause.presence !== lunr.Query.presence.PROHIBITED\n ))\n\n /* Perform search and post-process results */\n const groups = this.index.search(`${query}*`)\n\n /* Apply post-query boosts based on title and search query terms */\n .reduce((results, { ref, score, matchData }) => {\n const document = this.documents.get(ref)\n if (typeof document !== \"undefined\") {\n const { location, title, text, parent } = document\n\n /* Compute and analyze search query terms */\n const terms = getSearchQueryTerms(\n clauses,\n Object.keys(matchData.metadata)\n )\n\n /* Highlight title and text and apply post-query boosts */\n const boost = +!parent + +Object.values(terms).every(t => t)\n results.push({\n location,\n title: highlight(title),\n text: highlight(text),\n score: score * (1 + boost),\n terms\n })\n }\n return results\n }, [])\n\n /* Sort search results again after applying boosts */\n .sort((a, b) => b.score - a.score)\n\n /* Group search results by page */\n .reduce((results, result) => {\n const document = this.documents.get(result.location)\n if (typeof document !== \"undefined\") {\n const ref = \"parent\" in document\n ? document.parent!.location\n : document.location\n results.set(ref, [...results.get(ref) || [], result])\n }\n return results\n }, new Map())\n\n /* Expand grouped search results */\n return [...groups.values()]\n\n /* Log errors to console (for now) */\n } catch {\n // tslint:disable-next-line no-console\n console.warn(`Invalid query: ${query} – see https://bit.ly/2s3ChXG`)\n }\n }\n\n /* Return nothing in case of error or empty query */\n return []\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// @ts-ignore\nimport * as escapeHTML from \"escape-html\"\n\nimport { SearchIndexDocument } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search document\n */\nexport interface SearchDocument extends SearchIndexDocument {\n parent?: SearchIndexDocument /* Parent article */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search document mapping\n */\nexport type SearchDocumentMap = Map\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search document mapping\n *\n * @param docs - Search index documents\n *\n * @return Search document map\n */\nexport function setupSearchDocumentMap(\n docs: SearchIndexDocument[]\n): SearchDocumentMap {\n const documents = new Map()\n const parents = new Set()\n for (const doc of docs) {\n const [path, hash] = doc.location.split(\"#\")\n\n /* Extract location and title */\n const location = doc.location\n const title = doc.title\n\n /* Escape and cleanup text */\n const text = escapeHTML(doc.text)\n .replace(/\\s+(?=[,.:;!?])/g, \"\")\n .replace(/\\s+/g, \" \")\n\n /* Handle section */\n if (hash) {\n const parent = documents.get(path)!\n\n /* Ignore first section, override article */\n if (!parents.has(parent)) {\n parent.title = doc.title\n parent.text = text\n\n /* Remember that we processed the article */\n parents.add(parent)\n\n /* Add subsequent section */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n parent\n })\n }\n\n /* Add article */\n } else {\n documents.set(location, {\n location,\n title,\n text\n })\n }\n }\n return documents\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndexConfig } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search highlight function\n *\n * @param value - Value\n *\n * @return Highlighted value\n */\nexport type SearchHighlightFn = (value: string) => string\n\n/**\n * Search highlight factory function\n *\n * @param query - Query value\n *\n * @return Search highlight function\n */\nexport type SearchHighlightFactoryFn = (query: string) => SearchHighlightFn\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search highlighter\n *\n * @param config - Search index configuration\n *\n * @return Search highlight factory function\n */\nexport function setupSearchHighlighter(\n config: SearchIndexConfig\n): SearchHighlightFactoryFn {\n const separator = new RegExp(config.separator, \"img\")\n const highlight = (_: unknown, data: string, term: string) => {\n return `${data}${term}`\n }\n\n /* Return factory function */\n return (query: string) => {\n query = query\n .replace(/[\\s*+\\-:~^]+/g, \" \")\n .trim()\n\n /* Create search term match expression */\n const match = new RegExp(`(^|${config.separator})(${\n query\n .replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\")\n .replace(separator, \"|\")\n })`, \"img\")\n\n /* Highlight string value */\n return value => value\n .replace(match, highlight)\n .replace(/<\\/mark>(\\s+)]*>/img, \"\\$1\")\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query clause\n */\nexport interface SearchQueryClause {\n presence: lunr.Query.presence /* Clause presence */\n term: string /* Clause term */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search query terms\n */\nexport type SearchQueryTerms = Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Parse a search query for analysis\n *\n * @param value - Query value\n *\n * @return Search query clauses\n */\nexport function parseSearchQuery(\n value: string\n): SearchQueryClause[] {\n const query = new (lunr as any).Query([\"title\", \"text\"])\n const parser = new (lunr as any).QueryParser(value, query)\n\n /* Parse and return query clauses */\n parser.parse()\n return query.clauses\n}\n\n/**\n * Analyze the search query clauses in regard to the search terms found\n *\n * @param query - Search query clauses\n * @param terms - Search terms\n *\n * @return Search query terms\n */\nexport function getSearchQueryTerms(\n query: SearchQueryClause[], terms: string[]\n): SearchQueryTerms {\n const clauses = new Set(query)\n\n /* Match query clauses against terms */\n const result: SearchQueryTerms = {}\n for (let t = 0; t < terms.length; t++)\n for (const clause of clauses)\n if (terms[t].startsWith(clause.term)) {\n result[clause.term] = true\n clauses.delete(clause)\n }\n\n /* Annotate unmatched query clauses */\n for (const clause of clauses)\n result[clause.term] = false\n\n /* Return query terms */\n return result\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"lunr\"\n\nimport { Search, SearchIndexConfig } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Add support for usage with `iframe-worker` polyfill\n *\n * While `importScripts` is synchronous when executed inside of a web worker,\n * it's not possible to provide a synchronous polyfilled implementation. The\n * cool thing is that awaiting a non-Promise is a noop, so extending the type\n * definition to return a `Promise` shouldn't break anything.\n *\n * @see https://bit.ly/2PjDnXi - GitHub comment\n */\ndeclare global {\n function importScripts(...urls: string[]): Promise | void\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n */\nlet index: Search\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch (= import) multi-language support through `lunr-languages`\n *\n * This function will automatically import the stemmers necessary to process\n * the languages which were given through the search index configuration.\n *\n * If the worker runs inside of an `iframe` (when using `iframe-worker` as\n * a shim), the base URL for the stemmers to be loaded must be determined by\n * searching for the first `script` element with a `src` attribute, which will\n * contain the contents of this script.\n *\n * @param config - Search index configuration\n *\n * @return Promise resolving with no result\n */\nasync function setupSearchLanguages(\n config: SearchIndexConfig\n): Promise {\n let base = \"../lunr\"\n\n /* Detect `iframe-worker` and fix base URL */\n if (typeof parent !== \"undefined\" && \"IFrameWorker\" in parent) {\n const worker = document.querySelector(\"script[src]\")!\n const [path] = worker.src.split(\"/worker\")\n\n /* Prefix base with path */\n base = base.replace(\"..\", path)\n }\n\n /* Add scripts for languages */\n const scripts = []\n for (const lang of config.lang) {\n if (lang === \"ja\") scripts.push(`${base}/tinyseg.min.js`)\n if (lang !== \"en\") scripts.push(`${base}/min/lunr.${lang}.min.js`)\n }\n\n /* Add multi-language support */\n if (config.lang.length > 1)\n scripts.push(`${base}/min/lunr.multi.min.js`)\n\n /* Load scripts synchronously */\n if (scripts.length)\n await importScripts(\n `${base}/min/lunr.stemmer.support.min.js`,\n ...scripts\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Message handler\n *\n * @param message - Source message\n *\n * @return Target message\n */\nexport async function handler(\n message: SearchMessage\n): Promise {\n switch (message.type) {\n\n /* Search setup message */\n case SearchMessageType.SETUP:\n await setupSearchLanguages(message.data.config)\n index = new Search(message.data)\n return {\n type: SearchMessageType.READY\n }\n\n /* Search query message */\n case SearchMessageType.QUERY:\n return {\n type: SearchMessageType.RESULT,\n data: index ? index.search(message.data) : []\n }\n\n /* All other messages */\n default:\n throw new TypeError(\"Invalid message type\")\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Worker\n * ------------------------------------------------------------------------- */\n\naddEventListener(\"message\", async ev => {\n postMessage(await handler(ev.data))\n})\n"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/assets/stylesheets/main.3b61ea93.min.css b/docs/assets/stylesheets/main.3b61ea93.min.css deleted file mode 100644 index e1851c5..0000000 --- a/docs/assets/stylesheets/main.3b61ea93.min.css +++ /dev/null @@ -1,3 +0,0 @@ -html{box-sizing:border-box;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none}*,*::before,*::after{box-sizing:inherit}body{margin:0}a,button,label,input{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{display:block;box-sizing:content-box;height:.05rem;padding:0;overflow:visible;border:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:separate;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{margin:0;padding:0;font-size:inherit;background:transparent;border:0}input{border:0;outline:none}:root{--md-default-fg-color: hsla(0, 0%, 0%, 0.87);--md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);--md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);--md-default-bg-color: hsla(0, 0%, 100%, 1);--md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}:root>*{--md-code-fg-color: hsla(200, 18%, 26%, 1);--md-code-bg-color: hsla(0, 0%, 96%, 1);--md-code-hl-color: hsla(60, 100%, 50%, 0.5);--md-code-hl-number-color: hsla(0, 67%, 50%, 1);--md-code-hl-special-color: hsla(340, 83%, 47%, 1);--md-code-hl-function-color: hsla(291, 45%, 50%, 1);--md-code-hl-constant-color: hsla(250, 63%, 60%, 1);--md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);--md-code-hl-string-color: hsla(150, 63%, 30%, 1);--md-code-hl-name-color: var(--md-code-fg-color);--md-code-hl-operator-color: var(--md-default-fg-color--light);--md-code-hl-punctuation-color: var(--md-default-fg-color--light);--md-code-hl-comment-color: var(--md-default-fg-color--light);--md-code-hl-generic-color: var(--md-default-fg-color--light);--md-code-hl-variable-color: var(--md-default-fg-color--light);--md-typeset-color: var(--md-default-fg-color);--md-typeset-a-color: var(--md-primary-fg-color);--md-typeset-mark-color: hsla(60, 100%, 50%, 0.5);--md-typeset-del-color: hsla(6, 90%, 60%, 0.15);--md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);--md-typeset-kbd-color: hsla(0, 0%, 98%, 1);--md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);--md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);--md-admonition-fg-color: var(--md-default-fg-color);--md-admonition-bg-color: var(--md-default-bg-color);--md-footer-fg-color: hsla(0, 0%, 100%, 1);--md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-footer-bg-color: hsla(0, 0%, 0%, 0.87);--md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32)}.md-icon svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,input{color:var(--md-typeset-color);font-feature-settings:"kern","liga";font-family:-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,pre,kbd{color:var(--md-typeset-color);font-feature-settings:"kern";font-family:SFMono-Regular,Consolas,Menlo,monospace}:root{--md-typeset-table--ascending: url("data:image/svg+xml;charset=utf-8,");--md-typeset-table--descending: url("data:image/svg+xml;charset=utf-8,")}.md-typeset{font-size:.8rem;line-height:1.6;-webkit-print-color-adjust:exact;color-adjust:exact}@media print{.md-typeset{font-size:.68rem}}.md-typeset p,.md-typeset ul,.md-typeset ol,.md-typeset dl,.md-typeset blockquote{margin:1em 0}.md-typeset h1{margin:0 0 1.25em;color:var(--md-default-fg-color--light);font-weight:300;font-size:2em;line-height:1.3;letter-spacing:-0.01em}.md-typeset h2{margin:1.6em 0 .64em;font-weight:300;font-size:1.5625em;line-height:1.4;letter-spacing:-0.01em}.md-typeset h3{margin:1.6em 0 .8em;font-weight:400;font-size:1.25em;line-height:1.5;letter-spacing:-0.01em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{margin:1em 0;font-weight:700;letter-spacing:-0.01em}.md-typeset h5,.md-typeset h6{margin:1.25em 0;color:var(--md-default-fg-color--light);font-weight:700;font-size:.8em;letter-spacing:-0.01em}.md-typeset h5{text-transform:uppercase}.md-typeset hr{margin:1.5em 0;border-bottom:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a::before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset code,.md-typeset pre,.md-typeset kbd{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset pre,.md-typeset kbd{white-space:pre-wrap}}.md-typeset code{padding:0 .2941176471em;font-size:.85em;word-break:break-word;background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset code:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset h1 code,.md-typeset h2 code,.md-typeset h3 code,.md-typeset h4 code,.md-typeset h5 code,.md-typeset h6 code{margin:initial;padding:initial;background-color:transparent;box-shadow:none}.md-typeset a>code{color:currentColor}.md-typeset pre{position:relative;margin:1em 0;line-height:1.4}.md-typeset pre>code{display:block;margin:0;padding:.7720588235em 1.1764705882em;overflow:auto;word-break:normal;box-shadow:none;-webkit-box-decoration-break:slice;box-decoration-break:slice;touch-action:auto;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{width:.2rem;height:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 44.9375em){.md-typeset>pre{margin:1em -0.8rem}.md-typeset>pre code{border-radius:0}}.md-typeset kbd{display:inline-block;padding:0 .6666666667em;color:var(--md-default-fg-color);font-size:.75em;vertical-align:text-top;word-break:break-word;background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -0.1rem .2rem var(--md-typeset-kbd-accent-color) inset}.md-typeset mark{color:inherit;word-break:break-word;background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset abbr{text-decoration:none;border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help}@media(hover: none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:focus::after,.md-typeset abbr[title]:hover::after{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:absolute;left:0;display:inline-block;width:auto;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;max-width:80%;margin-top:2em;padding:.2rem .3rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border-radius:.1rem;content:attr(title)}}.md-typeset small{opacity:.75}.md-typeset sup,.md-typeset sub{margin-left:.078125em}[dir=rtl] .md-typeset sup,[dir=rtl] .md-typeset sub{margin-right:.078125em;margin-left:initial}.md-typeset blockquote{padding-left:.6rem;color:var(--md-default-fg-color--light);border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{padding-right:.6rem;padding-left:initial;border-right:.2rem solid var(--md-default-fg-color--lighter);border-left:initial}.md-typeset ul{list-style-type:disc}.md-typeset ul,.md-typeset ol{margin-left:.625em;padding:0}[dir=rtl] .md-typeset ul,[dir=rtl] .md-typeset ol{margin-right:.625em;margin-left:initial}.md-typeset ul ol,.md-typeset ol ol{list-style-type:lower-alpha}.md-typeset ul ol ol,.md-typeset ol ol ol{list-style-type:lower-roman}.md-typeset ul li,.md-typeset ol li{margin-bottom:.5em;margin-left:1.25em}[dir=rtl] .md-typeset ul li,[dir=rtl] .md-typeset ol li{margin-right:1.25em;margin-left:initial}.md-typeset ul li p,.md-typeset ul li blockquote,.md-typeset ol li p,.md-typeset ol li blockquote{margin:.5em 0}.md-typeset ul li:last-child,.md-typeset ol li:last-child{margin-bottom:0}.md-typeset ul li ul,.md-typeset ul li ol,.md-typeset ol li ul,.md-typeset ol li ol{margin:.5em 0 .5em .625em}[dir=rtl] .md-typeset ul li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ol li ol{margin-right:.625em;margin-left:initial}.md-typeset dd{margin:1em 0 1.5em 1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em;margin-left:initial}.md-typeset img,.md-typeset svg{max-width:100%;height:auto}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em;margin-left:0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em;margin-right:0}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset figure{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;margin:0 auto;text-align:center}.md-typeset figure img{display:block}.md-typeset figcaption{max-width:24rem;margin:1em auto 2em;font-style:italic}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){display:inline-block;max-width:100%;overflow:auto;font-size:.64rem;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) th>*:first-child,.md-typeset table:not([class]) td>*:first-child{margin-top:0}.md-typeset table:not([class]) th>*:last-child,.md-typeset table:not([class]) td>*:last-child{margin-bottom:0}.md-typeset table:not([class]) th:not([align]),.md-typeset table:not([class]) td:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) th:not([align]),[dir=rtl] .md-typeset table:not([class]) td:not([align]){text-align:right}.md-typeset table:not([class]) th{min-width:5rem;padding:.9375em 1.25em;color:var(--md-default-bg-color);vertical-align:top;background-color:var(--md-default-fg-color--light)}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{padding:.9375em 1.25em;vertical-align:top;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset table:not([class]) tr{transition:background-color 125ms}.md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) tr:first-child td{border-top:0}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}.md-typeset table th[role=columnheader]::after{display:inline-block;width:1.2em;height:1.2em;margin-left:.5em;vertical-align:sub;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-typeset table th[role=columnheader][aria-sort=ascending]::after{background-color:currentColor;-webkit-mask-image:var(--md-typeset-table--ascending);mask-image:var(--md-typeset-table--ascending)}.md-typeset table th[role=columnheader][aria-sort=descending]::after{background-color:currentColor;-webkit-mask-image:var(--md-typeset-table--descending);mask-image:var(--md-typeset-table--descending)}.md-typeset__scrollwrap{margin:1em -0.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;width:100%;margin:0;overflow:hidden}html{height:100%;overflow-x:hidden;font-size:125%}@media screen and (min-width: 100em){html{font-size:137.5%}}@media screen and (min-width: 125em){html{font-size:150%}}body{position:relative;display:flex;flex-direction:column;width:100%;min-height:100%;font-size:.5rem;background-color:var(--md-default-bg-color)}@media print{body{display:block}}@media screen and (max-width: 59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{max-width:61rem;margin-right:auto;margin-left:auto}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.md-toggle{display:none}.md-skip{position:fixed;z-index:-1;margin:.5rem;padding:.3rem .5rem;color:var(--md-default-bg-color);font-size:.64rem;background-color:var(--md-default-fg-color);border-radius:.1rem;transform:translateY(0.4rem);opacity:0}.md-skip:focus{z-index:10;transform:translateY(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 175ms 75ms}@page{margin:25mm}.md-announce{overflow:auto;background-color:var(--md-footer-bg-color)}@media print{.md-announce{display:none}}.md-announce__inner{margin:.6rem auto;padding:0 .8rem;color:var(--md-footer-fg-color);font-size:.7rem}.md-typeset .md-button{display:inline-block;padding:.625em 2em;color:var(--md-primary-fg-color);font-weight:700;border:.1rem solid currentColor;border-radius:.1rem;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{color:var(--md-accent-bg-color);background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}:root{--md-clipboard-icon: url("data:image/svg+xml;charset=utf-8,")}.md-clipboard{position:absolute;top:.5em;right:.5em;z-index:1;width:1.5em;height:1.5em;color:var(--md-default-fg-color--lightest);border-radius:.1rem;cursor:pointer;transition:color 250ms}@media print{.md-clipboard{display:none}}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard::after{display:block;width:1.125em;height:1.125em;margin:0 auto;background-color:currentColor;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-content{flex-grow:1;overflow:hidden;scroll-padding-top:51.2rem}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width: 76.25em){.md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem;margin-left:.8rem}.md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:.8rem;margin-left:1.2rem}}.md-content__inner::before{display:block;height:.4rem;content:""}.md-content__inner>:last-child{margin-bottom:0}.md-content__button{float:right;margin:.4rem 0;margin-left:.4rem;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left;margin-right:.4rem;margin-left:initial}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}.md-dialog{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:fixed;right:.8rem;bottom:.8rem;left:initial;z-index:2;display:block;min-width:11.1rem;padding:.4rem .6rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border:none;border-radius:.1rem;transform:translateY(100%);opacity:0;transition:transform 0ms 400ms,opacity 400ms}@media print{.md-dialog{display:none}}[dir=rtl] .md-dialog{right:initial;left:.8rem}.md-dialog[data-md-state=open]{transform:translateY(0);opacity:1;transition:transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),opacity 400ms}.md-header{position:-webkit-sticky;position:sticky;top:0;right:0;left:0;z-index:2;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem rgba(0,0,0,0),0 .2rem .4rem rgba(0,0,0,0);transition:color 250ms,background-color 250ms}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header-nav{display:flex;align-items:center;padding:0 .2rem}.md-header-nav__button{position:relative;z-index:1;display:inline-block;margin:.2rem;padding:.4rem;color:currentColor;vertical-align:middle;cursor:pointer;transition:opacity 250ms}.md-header-nav__button:focus,.md-header-nav__button:hover{opacity:.7}.md-header-nav__button:not(.focus-visible){outline:none}.md-header-nav__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width: 76.1875em){.md-header-nav__button.md-logo{display:none}}.md-header-nav__button.md-logo img,.md-header-nav__button.md-logo svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}@media screen and (min-width: 60em){.md-header-nav__button[for=__search]{display:none}}.no-js .md-header-nav__button[for=__search]{display:none}[dir=rtl] .md-header-nav__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width: 76.25em){.md-header-nav__button[for=__drawer]{display:none}}.md-header-nav__topic{position:absolute;display:flex;max-width:100%;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms}.md-header-nav__topic+.md-header-nav__topic{z-index:-1;transform:translateX(1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__topic+.md-header-nav__topic{transform:translateX(-1.25rem)}.md-header-nav__title{flex-grow:1;height:2.4rem;margin-right:.4rem;margin-left:1rem;font-size:.9rem;line-height:2.4rem}.md-header-nav__title[data-md-state=active] .md-header-nav__topic{z-index:-1;transform:translateX(-1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__title[data-md-state=active] .md-header-nav__topic{transform:translateX(1.25rem)}.md-header-nav__title[data-md-state=active] .md-header-nav__topic+.md-header-nav__topic{z-index:0;transform:translateX(0);opacity:1;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:initial}.md-header-nav__title>.md-header-nav__ellipsis{position:relative;width:100%;height:100%}.md-header-nav__source{display:none}@media screen and (min-width: 60em){.md-header-nav__source{display:block;width:11.7rem;max-width:11.7rem;margin-left:1rem}[dir=rtl] .md-header-nav__source{margin-right:1rem;margin-left:initial}}@media screen and (min-width: 76.25em){.md-header-nav__source{margin-left:1.4rem}[dir=rtl] .md-header-nav__source{margin-right:1.4rem}}.md-footer{color:var(--md-footer-fg-color);background-color:var(--md-footer-bg-color)}@media print{.md-footer{display:none}}.md-footer-nav__inner{padding:.2rem;overflow:auto}.md-footer-nav__link{display:flex;padding-top:1.4rem;padding-bottom:.4rem;transition:opacity 250ms}@media screen and (min-width: 45em){.md-footer-nav__link{width:50%}}.md-footer-nav__link:focus,.md-footer-nav__link:hover{opacity:.7}.md-footer-nav__link--prev{float:left}@media screen and (max-width: 44.9375em){.md-footer-nav__link--prev{width:25%}.md-footer-nav__link--prev .md-footer-nav__title{display:none}}[dir=rtl] .md-footer-nav__link--prev{float:right}[dir=rtl] .md-footer-nav__link--prev svg{transform:scaleX(-1)}.md-footer-nav__link--next{float:right;text-align:right}@media screen and (max-width: 44.9375em){.md-footer-nav__link--next{width:75%}}[dir=rtl] .md-footer-nav__link--next{float:left;text-align:left}[dir=rtl] .md-footer-nav__link--next svg{transform:scaleX(-1)}.md-footer-nav__title{position:relative;flex-grow:1;max-width:calc(100% - 2.4rem);padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-footer-nav__button{margin:.2rem;padding:.4rem}.md-footer-nav__direction{position:absolute;right:0;left:0;margin-top:-1rem;padding:0 1rem;font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-footer-copyright{width:100%;margin:auto .6rem;padding:.4rem 0;color:var(--md-footer-fg-color--lighter);font-size:.64rem}@media screen and (min-width: 45em){.md-footer-copyright{width:auto}}.md-footer-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-footer-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width: 45em){.md-footer-social{padding:.6rem 0}}.md-footer-social__link{display:inline-block;width:1.6rem;height:1.6rem;text-align:center}.md-footer-social__link::before{line-height:1.9}.md-footer-social__link svg{max-height:.8rem;vertical-align:-25%;fill:currentColor}:root{--md-nav-icon--prev: url("data:image/svg+xml;charset=utf-8,");--md-nav-icon--next: url("data:image/svg+xml;charset=utf-8,");--md-toc-icon: url("data:image/svg+xml;charset=utf-8,")}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;padding:0 .6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{width:auto;height:100%}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{display:block;width:2.4rem;height:2.4rem;fill:currentColor}.md-nav__list{margin:0;padding:0;list-style:none}.md-nav__item{padding:0 .6rem}.md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-right:.6rem;padding-left:0}.md-nav__link{display:block;margin-top:.625em;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:color 125ms;scroll-snap-align:start}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item--nested>.md-nav__link{color:inherit}.md-nav__link:focus,.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{display:block;width:100%;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);background-color:currentColor}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__source{display:none}@media screen and (max-width: 76.1875em){.md-nav--primary,.md-nav--primary .md-nav{position:absolute;top:0;right:0;left:0;z-index:1;display:flex;flex-direction:column;height:100%;background-color:var(--md-default-bg-color)}.md-nav--primary .md-nav__title,.md-nav--primary .md-nav__item{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{position:relative;height:5.6rem;padding:3rem .8rem .2rem;color:var(--md-default-fg-color--light);font-weight:400;line-height:2.4rem;white-space:nowrap;background-color:var(--md-default-fg-color--lightest);cursor:pointer}.md-nav--primary .md-nav__title .md-nav__icon{position:absolute;top:.4rem;left:.4rem;display:block;width:1.2rem;height:1.2rem;margin:.2rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem;left:initial}.md-nav--primary .md-nav__title .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-nav--primary .md-nav__title~.md-nav__list{overflow-y:auto;background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;-webkit-scroll-snap-type:y mandatory;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color)}.md-nav--primary .md-nav__title .md-logo{position:absolute;top:.2rem;left:.2rem;display:block;margin:.2rem;padding:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-logo{right:.2rem;left:initial}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{padding:0;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{position:relative;margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link .md-nav__icon{position:absolute;top:50%;right:.6rem;width:1.2rem;height:1.2rem;margin-top:-0.6rem;color:inherit;font-size:1.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{right:initial;left:.6rem}.md-nav--primary .md-nav__link .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-nav--primary .md-nav__icon::after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav__link{position:static}.md-nav--primary .md-nav--secondary .md-nav{position:static;background-color:transparent}.md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem;padding-left:initial}.md-nav--secondary{background-color:transparent}.md-nav__toggle~.md-nav{display:flex;transform:translateX(100%);opacity:0;transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{transform:translateX(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width: 59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:block;padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{display:block;padding:0 .2rem;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color--dark)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:block;padding-right:2.4rem;scroll-snap-align:initial}[dir=rtl] .md-nav--integrated .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--integrated .md-nav__link[for=__toc] .md-icon::after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width: 60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width: 76.25em){.md-nav{transition:max-height 250ms cubic-bezier(0.86, 0, 0.07, 1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__title{display:block;padding:0;pointer-events:none;scroll-snap-align:start}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{float:right;width:.9rem;height:.9rem;transition:transform 250ms}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon::after{display:inline-block;width:100%;height:100%;vertical-align:-0.1rem;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav>.md-nav__title{display:block;padding:0 .6rem;pointer-events:none;scroll-snap-align:start}.md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav__item{padding-right:.6rem}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:block;margin-bottom:1.25em;border-left:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav>.md-nav__title{display:none}}:root{--md-search-result-icon: url("data:image/svg+xml;charset=utf-8,")}.md-search{position:relative}@media screen and (min-width: 60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{z-index:1;opacity:0}@media screen and (max-width: 59.9375em){.md-search__overlay{position:absolute;top:.2rem;left:-2.2rem;width:2rem;height:2rem;overflow:hidden;background-color:var(--md-default-bg-color);border-radius:1rem;transform-origin:center;transition:transform 300ms 100ms,opacity 200ms 200ms;pointer-events:none}[dir=rtl] .md-search__overlay{right:-2.2rem;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform 400ms,opacity 100ms}}@media screen and (min-width: 60em){.md-search__overlay{position:fixed;top:0;left:0;width:0;height:0;background-color:rgba(0,0,0,.54);cursor:pointer;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[dir=rtl] .md-search__overlay{right:0;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@media screen and (max-width: 29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width: 30em)and (max-width: 44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width: 45em)and (max-width: 59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width: 59.9375em){.md-search__inner{position:fixed;top:0;left:100%;z-index:2;width:100%;height:100%;transform:translateX(5%);opacity:0;transition:right 0ms 300ms,left 0ms 300ms,transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),opacity 150ms 150ms}[data-md-toggle=search]:checked~.md-header .md-search__inner{left:0;transform:translateX(0);opacity:1;transition:right 0ms 0ms,left 0ms 0ms,transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms 150ms}[dir=rtl] [data-md-toggle=search]:checked~.md-header .md-search__inner{right:0;left:initial}html [dir=rtl] .md-search__inner{right:100%;left:initial;transform:translateX(-5%)}}@media screen and (min-width: 60em){.md-search__inner{position:relative;float:right;width:11.7rem;padding:.1rem 0;transition:width 250ms cubic-bezier(0.1, 0.7, 0.1, 1)}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width: 60em)and (max-width: 76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width: 76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{position:relative}@media screen and (min-width: 60em){.md-search__form{border-radius:.1rem}}.md-search__input{position:relative;z-index:2;padding:0 2.2rem 0 3.6rem;text-overflow:ellipsis;background-color:var(--md-default-bg-color);transition:color 250ms,background-color 250ms}[dir=rtl] .md-search__input{padding:0 3.6rem 0 2.2rem}.md-search__input::-webkit-input-placeholder{-webkit-transition:color 250ms;transition:color 250ms}.md-search__input::-moz-placeholder{-moz-transition:color 250ms;transition:color 250ms}.md-search__input::-ms-input-placeholder{-ms-transition:color 250ms;transition:color 250ms}.md-search__input::placeholder{transition:color 250ms}.md-search__input::-webkit-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input~.md-search__icon,.md-search__input::placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width: 59.9375em){.md-search__input{width:100%;height:2.4rem;font-size:.9rem}}@media screen and (min-width: 60em){.md-search__input{width:100%;height:1.8rem;padding-left:2.2rem;color:inherit;font-size:.8rem;background-color:rgba(0,0,0,.26);border-radius:.1rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}.md-search__input::-webkit-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-moz-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input:hover{background-color:rgba(255,255,255,.12)}[data-md-toggle=search]:checked~.md-header .md-search__input{color:var(--md-default-fg-color);text-overflow:clip;background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0}[data-md-toggle=search]:checked~.md-header .md-search__input::-webkit-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{position:absolute;z-index:2;width:1.2rem;height:1.2rem;cursor:pointer;transition:color 250ms,opacity 250ms}.md-search__icon:hover{opacity:.7}.md-search__icon[for=__search]{top:.3rem;left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem;left:initial}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width: 59.9375em){.md-search__icon[for=__search]{top:.6rem;left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem;left:initial}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width: 60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}.md-search__icon[type=reset]{top:.3rem;right:.5rem;transform:scale(0.75);opacity:0;transition:transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:none}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.5rem}@media screen and (max-width: 59.9375em){.md-search__icon[type=reset]{top:.6rem;right:.8rem}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]{transform:scale(1);opacity:1;pointer-events:initial}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]:hover{opacity:.7}.md-search__output{position:absolute;z-index:1;width:100%;overflow:hidden;border-radius:0 0 .1rem .1rem}@media screen and (max-width: 59.9375em){.md-search__output{top:2.4rem;bottom:0}}@media screen and (min-width: 60em){.md-search__output{top:1.9rem;opacity:0;transition:opacity 400ms}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12),0 3px 5px -1px rgba(0,0,0,.4);opacity:1}}.md-search__scrollwrap{height:100%;overflow-y:auto;background-color:var(--md-default-bg-color);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-scroll-snap-type:y mandatory;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}@media(-webkit-max-device-pixel-ratio: 1), (max-resolution: 1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width: 76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width: 60em){.md-search__scrollwrap{max-height:0;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{padding:0 .8rem;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;background-color:var(--md-default-fg-color--lightest);scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem;padding-left:initial}}.md-search-result__list{margin:0;padding:0;list-style:none}.md-search-result__item{box-shadow:0 -0.05rem 0 var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;transition:background-color 250ms;scroll-snap-align:start}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{display:block;padding:.75em .8rem;color:var(--md-typeset-a-color);font-size:.64rem;outline:0;cursor:pointer;transition:color 250ms,background-color 250ms;scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__more summary:focus,.md-search-result__more summary:hover{color:var(--md-accent-fg-color);background-color:var(--md-accent-fg-color--transparent)}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{position:relative;padding:0 .8rem;overflow:hidden}@media screen and (min-width: 60em){.md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__article--document .md-search-result__title{margin:.55rem 0;font-weight:400;font-size:.8rem;line-height:1.4}.md-search-result__icon{position:absolute;left:0;width:1.2rem;height:1.2rem;margin:.5rem;color:var(--md-default-fg-color--light)}@media screen and (max-width: 59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon::after{display:inline-block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-search-result__icon{right:0;left:initial}[dir=rtl] .md-search-result__icon::after{transform:scaleX(-1)}.md-search-result__title{margin:.5em 0;font-weight:700;font-size:.64rem;line-height:1.6}.md-search-result__teaser{display:-webkit-box;max-height:2rem;margin:.5em 0;overflow:hidden;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6;text-overflow:ellipsis;-webkit-box-orient:vertical;-webkit-line-clamp:2}@media screen and (max-width: 44.9375em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}.md-search-result__teaser mark{text-decoration:underline;background-color:transparent}.md-search-result__terms{margin:.5em 0;font-size:.64rem;font-style:italic}.md-search-result mark{color:var(--md-accent-fg-color);background-color:transparent}.md-sidebar{position:-webkit-sticky;position:sticky;top:2.4rem;flex-shrink:0;align-self:flex-start;width:12.1rem;height:0;padding:1.2rem 0}@media print{.md-sidebar{display:none}}@media screen and (max-width: 76.1875em){.md-sidebar--primary{position:fixed;top:0;left:-12.1rem;z-index:3;display:block;width:12.1rem;height:100%;background-color:var(--md-default-bg-color);transform:translateX(0);transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 250ms}[dir=rtl] .md-sidebar--primary{right:-12.1rem;left:initial}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.4);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{position:absolute;top:0;right:0;bottom:0;left:0;margin:0;-webkit-scroll-snap-type:none;-ms-scroll-snap-type:none;scroll-snap-type:none;overflow:hidden}}@media screen and (min-width: 76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width: 60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{margin:0 .2rem;overflow-y:auto;-webkit-backface-visibility:hidden;backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 76.1875em){.md-overlay{position:fixed;top:0;z-index:3;width:0;height:0;background-color:rgba(0,0,0,.54);opacity:0;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[data-md-toggle=drawer]:checked~.md-overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@-webkit-keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@-webkit-keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}@keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}.md-source{display:block;font-size:.65rem;line-height:1.2;white-space:nowrap;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:opacity 250ms}.md-source:focus,.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;width:2.4rem;height:2.4rem;vertical-align:middle}.md-source__icon svg{margin-top:.6rem;margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem;margin-left:initial}.md-source__icon+.md-source__repository{margin-left:-2rem;padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem;margin-left:initial;padding-right:2rem;padding-left:initial}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);margin-left:.6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{margin:0;padding:0;overflow:hidden;font-weight:700;font-size:.55rem;list-style-type:none;opacity:.75}[data-md-state=done] .md-source__facts{-webkit-animation:md-source__facts--done 250ms ease-in;animation:md-source__facts--done 250ms ease-in}.md-source__fact{float:left}[dir=rtl] .md-source__fact{float:right}[data-md-state=done] .md-source__fact{-webkit-animation:md-source__fact--done 400ms ease-out;animation:md-source__fact--done 400ms ease-out}.md-source__fact::before{margin:0 .1rem;content:"·"}.md-source__fact:first-child::before{display:none}.md-tabs{width:100%;overflow:auto;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);transition:background-color 250ms}@media print{.md-tabs{display:none}}@media screen and (max-width: 76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}.md-tabs__list{margin:0;margin-left:.2rem;padding:0;white-space:nowrap;list-style:none;contain:content}[dir=rtl] .md-tabs__list{margin-right:.2rem;margin-left:initial}.md-tabs__item{display:inline-block;height:2.4rem;padding-right:.6rem;padding-left:.6rem}.md-tabs__link{display:block;margin-top:.8rem;font-size:.7rem;-webkit-backface-visibility:hidden;backface-visibility:hidden;opacity:.7;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 250ms}.md-tabs__link--active,.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:100ms}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:120ms}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:140ms}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:160ms}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:180ms}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:200ms}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:220ms}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:240ms}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:260ms}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:280ms}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:300ms}.md-tabs[data-md-state=hidden] .md-tabs__link{transform:translateY(50%);opacity:0;transition:transform 0ms 100ms,opacity 100ms}:root{--md-admonition-icon--note: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--abstract: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--info: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--tip: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--success: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--question: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--warning: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--failure: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--danger: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--bug: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--example: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--quote: url( "data:image/svg+xml;charset=utf-8," )}.md-typeset .admonition,.md-typeset details{margin:1.5625em 0;padding:0 .6rem;overflow:hidden;color:var(--md-admonition-fg-color);font-size:.64rem;page-break-inside:avoid;background-color:var(--md-admonition-bg-color);border-left:.2rem solid #448aff;border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 .025rem .05rem rgba(0,0,0,.05)}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}[dir=rtl] .md-typeset .admonition,[dir=rtl] .md-typeset details{border-right:.2rem solid #448aff;border-left:none}.md-typeset .admonition .admonition,.md-typeset details .admonition,.md-typeset .admonition details,.md-typeset details details{margin:1em 0}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -0.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}.md-typeset .admonition-title,.md-typeset summary{position:relative;margin:0 -0.6rem 0 -0.8rem;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(68,138,255,.1);border-left:.2rem solid #448aff}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{margin:0 -0.8rem 0 -0.6rem;padding:.4rem 2rem .4rem .6rem;border-right:.2rem solid #448aff;border-left:none}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}.md-typeset .admonition-title::before,.md-typeset summary::before{position:absolute;left:.6rem;width:1rem;height:1rem;background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .admonition-title::before,[dir=rtl] .md-typeset summary::before{right:.6rem;left:initial}.md-typeset .admonition-title code,.md-typeset summary code{margin:initial;padding:initial;color:currentColor;background-color:transparent;border-radius:initial;box-shadow:none}.md-typeset .admonition-title+.tabbed-set:last-child,.md-typeset summary+.tabbed-set:last-child{margin-top:0}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:rgba(68,138,255,.1);border-color:#448aff}.md-typeset .note>.admonition-title::before,.md-typeset .note>summary::before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.abstract,.md-typeset details.abstract,.md-typeset .admonition.tldr,.md-typeset details.tldr,.md-typeset .admonition.summary,.md-typeset details.summary{border-color:#00b0ff}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary,.md-typeset .tldr>.admonition-title,.md-typeset .tldr>summary,.md-typeset .summary>.admonition-title,.md-typeset .summary>summary{background-color:rgba(0,176,255,.1);border-color:#00b0ff}.md-typeset .abstract>.admonition-title::before,.md-typeset .abstract>summary::before,.md-typeset .tldr>.admonition-title::before,.md-typeset .tldr>summary::before,.md-typeset .summary>.admonition-title::before,.md-typeset .summary>summary::before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.info,.md-typeset details.info,.md-typeset .admonition.todo,.md-typeset details.todo{border-color:#00b8d4}.md-typeset .info>.admonition-title,.md-typeset .info>summary,.md-typeset .todo>.admonition-title,.md-typeset .todo>summary{background-color:rgba(0,184,212,.1);border-color:#00b8d4}.md-typeset .info>.admonition-title::before,.md-typeset .info>summary::before,.md-typeset .todo>.admonition-title::before,.md-typeset .todo>summary::before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.tip,.md-typeset details.tip,.md-typeset .admonition.important,.md-typeset details.important,.md-typeset .admonition.hint,.md-typeset details.hint{border-color:#00bfa5}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary,.md-typeset .important>.admonition-title,.md-typeset .important>summary,.md-typeset .hint>.admonition-title,.md-typeset .hint>summary{background-color:rgba(0,191,165,.1);border-color:#00bfa5}.md-typeset .tip>.admonition-title::before,.md-typeset .tip>summary::before,.md-typeset .important>.admonition-title::before,.md-typeset .important>summary::before,.md-typeset .hint>.admonition-title::before,.md-typeset .hint>summary::before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.success,.md-typeset details.success,.md-typeset .admonition.done,.md-typeset details.done,.md-typeset .admonition.check,.md-typeset details.check{border-color:#00c853}.md-typeset .success>.admonition-title,.md-typeset .success>summary,.md-typeset .done>.admonition-title,.md-typeset .done>summary,.md-typeset .check>.admonition-title,.md-typeset .check>summary{background-color:rgba(0,200,83,.1);border-color:#00c853}.md-typeset .success>.admonition-title::before,.md-typeset .success>summary::before,.md-typeset .done>.admonition-title::before,.md-typeset .done>summary::before,.md-typeset .check>.admonition-title::before,.md-typeset .check>summary::before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.question,.md-typeset details.question,.md-typeset .admonition.faq,.md-typeset details.faq,.md-typeset .admonition.help,.md-typeset details.help{border-color:#64dd17}.md-typeset .question>.admonition-title,.md-typeset .question>summary,.md-typeset .faq>.admonition-title,.md-typeset .faq>summary,.md-typeset .help>.admonition-title,.md-typeset .help>summary{background-color:rgba(100,221,23,.1);border-color:#64dd17}.md-typeset .question>.admonition-title::before,.md-typeset .question>summary::before,.md-typeset .faq>.admonition-title::before,.md-typeset .faq>summary::before,.md-typeset .help>.admonition-title::before,.md-typeset .help>summary::before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.warning,.md-typeset details.warning,.md-typeset .admonition.attention,.md-typeset details.attention,.md-typeset .admonition.caution,.md-typeset details.caution{border-color:#ff9100}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary,.md-typeset .attention>.admonition-title,.md-typeset .attention>summary,.md-typeset .caution>.admonition-title,.md-typeset .caution>summary{background-color:rgba(255,145,0,.1);border-color:#ff9100}.md-typeset .warning>.admonition-title::before,.md-typeset .warning>summary::before,.md-typeset .attention>.admonition-title::before,.md-typeset .attention>summary::before,.md-typeset .caution>.admonition-title::before,.md-typeset .caution>summary::before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.failure,.md-typeset details.failure,.md-typeset .admonition.missing,.md-typeset details.missing,.md-typeset .admonition.fail,.md-typeset details.fail{border-color:#ff5252}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary,.md-typeset .missing>.admonition-title,.md-typeset .missing>summary,.md-typeset .fail>.admonition-title,.md-typeset .fail>summary{background-color:rgba(255,82,82,.1);border-color:#ff5252}.md-typeset .failure>.admonition-title::before,.md-typeset .failure>summary::before,.md-typeset .missing>.admonition-title::before,.md-typeset .missing>summary::before,.md-typeset .fail>.admonition-title::before,.md-typeset .fail>summary::before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.danger,.md-typeset details.danger,.md-typeset .admonition.error,.md-typeset details.error{border-color:#ff1744}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary,.md-typeset .error>.admonition-title,.md-typeset .error>summary{background-color:rgba(255,23,68,.1);border-color:#ff1744}.md-typeset .danger>.admonition-title::before,.md-typeset .danger>summary::before,.md-typeset .error>.admonition-title::before,.md-typeset .error>summary::before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:rgba(245,0,87,.1);border-color:#f50057}.md-typeset .bug>.admonition-title::before,.md-typeset .bug>summary::before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.example,.md-typeset details.example{border-color:#651fff}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:rgba(101,31,255,.1);border-color:#651fff}.md-typeset .example>.admonition-title::before,.md-typeset .example>summary::before{background-color:#651fff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.quote,.md-typeset details.quote,.md-typeset .admonition.cite,.md-typeset details.cite{border-color:#9e9e9e}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary,.md-typeset .cite>.admonition-title,.md-typeset .cite>summary{background-color:rgba(158,158,158,.1);border-color:#9e9e9e}.md-typeset .quote>.admonition-title::before,.md-typeset .quote>summary::before,.md-typeset .cite>.admonition-title::before,.md-typeset .cite>summary::before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}:root{--md-footnotes-icon: url("data:image/svg+xml;charset=utf-8,")}.md-typeset [id^="fnref:"]:target{scroll-margin-top:initial;margin-top:-3.4rem;padding-top:3.4rem}.md-typeset [id^="fn:"]:target{scroll-margin-top:initial;margin-top:-3.45rem;padding-top:3.45rem}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}.md-typeset .footnote ol{margin-left:0}.md-typeset .footnote li{transition:color 125ms}.md-typeset .footnote li:target{color:var(--md-default-fg-color)}.md-typeset .footnote li:hover .footnote-backref,.md-typeset .footnote li:target .footnote-backref{transform:translateX(0);opacity:1}.md-typeset .footnote li>:first-child{margin-top:0}.md-typeset .footnote-backref{display:inline-block;color:var(--md-typeset-a-color);font-size:0;vertical-align:text-bottom;transform:translateX(0.25rem);opacity:0;transition:color 250ms,transform 250ms 250ms,opacity 125ms 250ms}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);transform:translateX(0);opacity:1}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-0.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref::before{display:inline-block;width:.8rem;height:.8rem;background-color:currentColor;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .footnote-backref::before svg{transform:scaleX(-1)}.md-typeset .headerlink{display:inline-block;margin-left:.5rem;color:var(--md-default-fg-color--lighter);opacity:0;transition:color 250ms,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem;margin-left:initial}.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink,.md-typeset .headerlink:focus{opacity:1;transition:color 250ms,opacity 125ms}.md-typeset :target>.headerlink,.md-typeset .headerlink:focus,.md-typeset .headerlink:hover{color:var(--md-accent-fg-color)}.md-typeset :target{scroll-margin-top:3.6rem}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{scroll-margin-top:initial}.md-typeset h1:target::before,.md-typeset h2:target::before,.md-typeset h3:target::before{display:block;margin-top:-3.4rem;padding-top:3.4rem;content:""}.md-typeset h4:target{scroll-margin-top:initial}.md-typeset h4:target::before{display:block;margin-top:-3.45rem;padding-top:3.45rem;content:""}.md-typeset h5:target,.md-typeset h6:target{scroll-margin-top:initial}.md-typeset h5:target::before,.md-typeset h6:target::before{display:block;margin-top:-3.6rem;padding-top:3.6rem;content:""}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width: 44.9375em){.md-typeset div.arithmatex{margin:0 -0.8rem}}.md-typeset div.arithmatex>*{width:-webkit-min-content;width:-moz-min-content;width:min-content;margin:1em auto !important;padding:0 .8rem;touch-action:auto}.md-typeset del.critic,.md-typeset ins.critic,.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment::before{content:"/* "}.md-typeset .critic.comment::after{content:" */"}.md-typeset .critic.block{display:block;margin:1em 0;padding-right:.8rem;padding-left:.8rem;overflow:auto;box-shadow:none}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon: url("data:image/svg+xml;charset=utf-8,")}.md-typeset details{display:block;padding-top:0;overflow:visible}.md-typeset details[open]>summary::after{transform:rotate(90deg)}.md-typeset details:not([open]){padding-bottom:0;box-shadow:none}.md-typeset details:not([open])>summary{border-radius:.1rem}.md-typeset details::after{display:table;content:""}.md-typeset summary{display:block;min-height:1rem;padding:.4rem 1.8rem .4rem 2rem;border-top-left-radius:.1rem;border-top-right-radius:.1rem;cursor:pointer}[dir=rtl] .md-typeset summary{padding:.4rem 2.2rem .4rem 1.8rem}.md-typeset summary:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset summary::after{position:absolute;top:.4rem;right:.4rem;width:1rem;height:1rem;background-color:currentColor;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transform:rotate(0deg);transition:transform 250ms;content:""}[dir=rtl] .md-typeset summary::after{right:initial;left:.4rem;transform:rotate(180deg)}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .twemoji,.md-typeset .gemoji{display:inline-block;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .twemoji svg,.md-typeset .gemoji svg{width:1.125em;max-height:100%;fill:currentColor}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .sb,.highlight .sc,.highlight .s2,.highlight .si,.highlight .s1,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .m,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .no,.highlight .nb,.highlight .bp{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .cm,.highlight .c1,.highlight .ch,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gr,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gs,.highlight .gu,.highlight .gt{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{margin:0 -0.125em;padding:0 .125em;border-radius:.1rem}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em;background-color:var(--md-code-hl-color)}.highlight [data-linenos]::before{position:-webkit-sticky;position:sticky;left:-1.1764705882em;float:left;margin-right:1.1764705882em;margin-left:-1.1764705882em;padding-left:1.1764705882em;color:var(--md-default-fg-color--light);background-color:var(--md-code-bg-color);box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset;content:attr(data-linenos);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable{display:flow-root;overflow:hidden}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable .linenos{padding:.7720588235em 1.1764705882em;padding-right:0;font-size:.85em;background-color:var(--md-code-bg-color);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable .linenodiv{padding-right:.5882352941em;box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;overflow:hidden}.md-typeset .highlighttable{margin:1em 0;direction:ltr;border-radius:.1rem}.md-typeset .highlighttable code{border-radius:0}@media screen and (max-width: 44.9375em){.md-typeset>.highlight{margin:1em -0.8rem}.md-typeset>.highlight .hll{margin:0 -0.8rem;padding:0 .8rem}.md-typeset>.highlight code{border-radius:0}.md-typeset>.highlighttable{margin:1em -0.8rem;border-radius:0}.md-typeset>.highlighttable .hll{margin:0 -0.8rem;padding:0 .8rem}}.md-typeset .keys kbd::before,.md-typeset .keys kbd::after{position:relative;margin:0;color:inherit;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial}.md-typeset .keys span{padding:0 .2em;color:var(--md-default-fg-color--light)}.md-typeset .keys .key-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-left-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-right-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-left-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-right-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-left-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-right-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-left-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-right-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-left-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-right-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-left-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-right-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-left-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-right-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-left-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-right-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-arrow-down::before{padding-right:.4em;content:"↓"}.md-typeset .keys .key-arrow-left::before{padding-right:.4em;content:"←"}.md-typeset .keys .key-arrow-right::before{padding-right:.4em;content:"→"}.md-typeset .keys .key-arrow-up::before{padding-right:.4em;content:"↑"}.md-typeset .keys .key-backspace::before{padding-right:.4em;content:"⌫"}.md-typeset .keys .key-backtab::before{padding-right:.4em;content:"⇤"}.md-typeset .keys .key-caps-lock::before{padding-right:.4em;content:"⇪"}.md-typeset .keys .key-clear::before{padding-right:.4em;content:"⌧"}.md-typeset .keys .key-context-menu::before{padding-right:.4em;content:"☰"}.md-typeset .keys .key-delete::before{padding-right:.4em;content:"⌦"}.md-typeset .keys .key-eject::before{padding-right:.4em;content:"⏏"}.md-typeset .keys .key-end::before{padding-right:.4em;content:"⤓"}.md-typeset .keys .key-escape::before{padding-right:.4em;content:"⎋"}.md-typeset .keys .key-home::before{padding-right:.4em;content:"⤒"}.md-typeset .keys .key-insert::before{padding-right:.4em;content:"⎀"}.md-typeset .keys .key-page-down::before{padding-right:.4em;content:"⇟"}.md-typeset .keys .key-page-up::before{padding-right:.4em;content:"⇞"}.md-typeset .keys .key-print-screen::before{padding-right:.4em;content:"⎙"}.md-typeset .keys .key-tab::after{padding-left:.4em;content:"⇥"}.md-typeset .keys .key-num-enter::after{padding-left:.4em;content:"⌤"}.md-typeset .keys .key-enter::after{padding-left:.4em;content:"⏎"}.md-typeset .tabbed-content{display:none;order:99;width:100%;box-shadow:0 -0.05rem var(--md-default-fg-color--lightest)}@media print{.md-typeset .tabbed-content{display:block;order:initial}}.md-typeset .tabbed-content>pre:only-child,.md-typeset .tabbed-content>.highlight:only-child pre,.md-typeset .tabbed-content>.highlighttable:only-child{margin:0}.md-typeset .tabbed-content>pre:only-child>code,.md-typeset .tabbed-content>.highlight:only-child pre>code,.md-typeset .tabbed-content>.highlighttable:only-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-content>.tabbed-set{margin:0}.md-typeset .tabbed-set{position:relative;display:flex;flex-wrap:wrap;margin:1em 0;border-radius:.1rem}.md-typeset .tabbed-set>input{position:absolute;width:0;height:0;opacity:0}.md-typeset .tabbed-set>input:checked+label{color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:checked+label+.tabbed-content{display:block}.md-typeset .tabbed-set>input:focus+label{outline-style:auto}.md-typeset .tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.md-typeset .tabbed-set>label{z-index:1;width:auto;padding:.9375em 1.25em .78125em;color:var(--md-default-fg-color--light);font-weight:700;font-size:.64rem;border-bottom:.1rem solid transparent;cursor:pointer;transition:color 250ms}.md-typeset .tabbed-set>label:hover{color:var(--md-accent-fg-color)}:root{--md-tasklist-icon: url( "data:image/svg+xml;charset=utf-8," );--md-tasklist-icon--checked: url( "data:image/svg+xml;charset=utf-8," )}.md-typeset .task-list-item{position:relative;list-style-type:none}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em;left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em;left:initial}.md-typeset .task-list-control [type=checkbox]{z-index:-1;opacity:0}.md-typeset .task-list-indicator::before{position:absolute;top:.15em;left:-1.5em;width:1.25em;height:1.25em;background-color:var(--md-default-fg-color--lightest);-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .task-list-indicator::before{right:-1.5em;left:initial}.md-typeset [type=checkbox]:checked+.task-list-indicator::before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)} - -/*# sourceMappingURL=main.3b61ea93.min.css.map*/ \ No newline at end of file diff --git a/docs/assets/stylesheets/main.3b61ea93.min.css.map b/docs/assets/stylesheets/main.3b61ea93.min.css.map deleted file mode 100644 index 5472d03..0000000 --- a/docs/assets/stylesheets/main.3b61ea93.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/assets/stylesheets/main.scss","webpack:///./src/assets/stylesheets/main/_reset.scss","webpack:///./src/assets/stylesheets/main/_colors.scss","webpack:///./src/assets/stylesheets/main/_icons.scss","webpack:///./src/assets/stylesheets/main/_typeset.scss","webpack:///./src/assets/stylesheets/utilities/_break.scss","webpack:///./node_modules/material-shadows/material-shadows.scss","webpack:///./src/assets/stylesheets/main/layout/_base.scss","webpack:///./src/assets/stylesheets/main/layout/_announce.scss","webpack:///./src/assets/stylesheets/main/layout/_button.scss","webpack:///./src/assets/stylesheets/main/layout/_clipboard.scss","webpack:///./src/assets/stylesheets/main/layout/_content.scss","webpack:///./src/assets/stylesheets/main/layout/_dialog.scss","webpack:///./src/assets/stylesheets/main/layout/_header.scss","webpack:///./src/assets/stylesheets/main/layout/_footer.scss","webpack:///./src/assets/stylesheets/main/layout/_nav.scss","webpack:///./src/assets/stylesheets/main/layout/_search.scss","webpack:///./src/assets/stylesheets/main/layout/_sidebar.scss","webpack:///./src/assets/stylesheets/main/layout/_source.scss","webpack:///./src/assets/stylesheets/main/layout/_tabs.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_admonition.scss","webpack:///./node_modules/material-design-color/material-color.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_toc.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_details.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss"],"names":[],"mappings":"AAAA,KC4BA,qBACE,8BACA,CADA,0BACA,CADA,yBACA,CADA,qBACA,sBAIF,kBAGE,MAIF,QACE,sBAIF,uCAIE,GAIF,aACE,qBACA,IAIF,aACE,uBACA,cACA,UACA,iBACA,SACA,OAIF,aACE,SAIF,eAEE,KAIF,iBACE,OAIF,wBACE,iBACA,OAIF,eAEE,mBACA,QAIF,QACE,UACA,kBACA,uBACA,SACA,OAIF,QACE,aACA,OCnFF,4CAGE,oDACA,sDACA,uDACA,4CACA,qDACA,uDACA,yDACA,8CAGA,qDACA,oDACA,4CACA,qDACA,6CAGA,4DACA,2CACA,oDACA,SAGA,0CAGE,wCACA,6CAGA,gDACA,mDACA,oDACA,oDACA,mDACA,kDACA,iDACA,+DACA,kEACA,8DACA,8DACA,+DACA,+CAGA,iDACA,kDAGA,gDAGA,kDACA,4CAGA,sDACA,mDACA,qDAGA,qDACA,2CAGA,oDACA,sDACA,4CACA,kDACA,cCrEF,aACE,aACA,cACA,kBACA,MCPJ,kCACE,kCACA,YAIF,6BAEE,oCACA,wEACA,cAIF,6BAGE,6BACA,oDACA,OAQF,wcACE,ucACA,aAOF,eACE,gBACA,iCACA,CADA,kBACA,cAIA,YAPF,gBAQI,oFAIF,YAKE,gBAIF,iBACE,wCACA,gBACA,cACA,gBACA,uBACA,gBAIF,oBACE,gBACA,mBACA,gBACA,uBACA,gBAIF,mBACE,gBACA,iBACA,gBACA,uBACA,mBAIF,eACE,gBAIF,YACE,gBACA,uBACA,+BAIF,eAEE,wCACA,gBACA,eACA,uBACA,gBAIF,wBACE,gBAIF,cACE,gEACA,eAIF,+BACE,sBACA,qCAGA,sBAEE,yCAIF,+BAEE,kDAKJ,6BAGE,cACA,cAGA,iDAPF,oBAQI,mBAKJ,uBACE,gBACA,sBACA,yCACA,oBACA,mCACA,CADA,0BACA,sCAGA,YACE,wCACA,yHAKJ,cAME,gBACA,6BACA,gBACA,oBAIF,kBACE,iBAIF,iBACE,aACA,gBACA,sBAGA,aACE,SACA,qCACA,cACA,kBACA,gBACA,mCACA,CADA,0BACA,kBACA,qBACA,gEACA,4BAGA,qDACE,yCAIF,WACE,aACA,+CAIF,oDACE,qDAGA,0CACE,0CCxCN,gBDkDA,kBACE,sBAGA,eACE,kBAMN,oBACE,wBACA,iCACA,gBACA,wBACA,sBACA,6CACA,oBACA,qKAEE,kBAMJ,aACE,sBACA,8CACA,mCACA,CADA,0BACA,kBAIF,oBACE,8DACA,YACA,qBAGA,iBANF,iBAOI,2EAGA,gGEnRJ,kBFuRM,OACA,qBACA,WACA,8BACA,CADA,0BACA,CADA,qBACA,cACA,eACA,oBACA,iCACA,gBACA,4CACA,oBACA,oBACA,oBAON,WACE,iCAIF,qBAEE,qDAGA,sBACE,oBACA,wBAKJ,kBACE,wCACA,4DACA,kCAGA,mBACE,qBACA,6DACA,oBACA,gBAKJ,oBACE,+BAIF,kBAEE,UACA,mDAGA,mBACE,oBACA,qCAIF,2BACE,2CAGA,2BACE,qCAKJ,kBACE,mBACA,yDAGA,mBACE,oBACA,mGAIF,aAEE,2DAIF,eACE,qFAIF,yBAEE,6HAGA,mBACE,oBACA,gBAOR,0BACE,0BAGA,oBACE,oBACA,iCAKJ,cAEE,YACA,yDAGA,UACE,cACA,2DAIF,UACE,eACA,qEAIF,YACE,oBAKJ,yBACE,CADF,sBACE,CADF,iBACE,eACA,cACA,kBACA,wBAGA,aACE,wBAKJ,eACE,oBACA,kBACA,oBAIF,cACE,gCAIF,oBACE,eACA,cACA,iBACA,4CACA,oBACA,mEAEE,kBAEF,cAGA,+BAbF,aAcI,mCAMF,gBACE,iGAQA,YACE,+FAIF,eACE,+FAKJ,eAEE,mHAGA,gBACE,mCAKJ,cACE,uBACA,iCACA,mBACA,mDACA,qCAGA,aACE,mCAKJ,sBACE,mBACA,6DACA,mCAIF,iCACE,yCAGA,iCACE,uDACA,kDAIF,YACE,kCAKJ,iBACE,yCAKJ,cACE,gDAGA,oBACE,YACA,aACA,iBACA,mBACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,qEAIF,6BACE,sDACA,CADA,6CACA,sEAIF,6BACE,uDACA,CADA,8CACA,yBAKJ,kBACE,gBACA,kBACA,oBAIF,oBACE,mBACA,gBACA,cAGA,mBANF,aAOI,gCAIF,aACE,WACA,SACA,gBACA,MGplBN,WACE,kBACA,eAOA,sCFuJE,KEhKJ,gBAaI,uCFmJA,KEhKJ,cAkBI,OAMJ,iBACE,aACA,sBACA,WACA,gBACA,gBAGA,4CACA,cAGA,KAZF,aAaI,2CF6IA,yBEzIF,cAII,WAUN,eACE,kBACA,iBACA,eAIF,YACE,sBACA,YACA,cAGA,cANF,aAOI,WAKJ,WACE,iBAGA,YACE,YACA,kBACA,cAKJ,eACE,mBACA,uBACA,YASF,YACE,UAIF,cACE,WAGA,aACA,oBACA,iCACA,iBACA,4CACA,oBACA,6BACA,UACA,gBAGA,UACE,wBACA,UACA,2EAEE,OAUN,WACE,cCtIF,aACE,2CACA,cAGA,aALF,YAMI,sBAIF,iBACE,gBACA,gCACA,gBACA,wBCXF,oBACE,mBACA,iCACA,gBACA,gCACA,oBACA,iEAEE,iCAKF,gCACE,4CACA,wCACA,2DAIF,+BAEE,2CACA,uCACA,OC3BN,mfACE,eAMF,iBACE,SACA,WACA,UACA,YACA,aACA,2CACA,oBACA,eACA,uBACA,cAGA,cAbF,YAcI,uBAIF,uCACE,yCAIF,+BAEE,sBAKF,aACE,cACA,eACA,cACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,aC9CJ,WACE,gBAMA,2BACA,oBAGA,qBACE,kBACA,wCNmJA,kEM7IE,kBACE,6EAGA,mBACE,kBACA,qEAKJ,mBACE,+EAGA,kBACE,mBACA,6BAON,aACE,aACA,WACA,gCAIF,eACE,qBAMJ,WACE,eACA,kBACA,UACA,cAGA,oBAPF,YAQI,gCAIF,UACE,mBACA,oBACA,mCAGA,oBACE,iCAKJ,yCACE,yBAIF,cACE,mBACA,YCxFN,gGNFE,eMKA,YACA,aACA,aACA,UACA,cACA,kBACA,oBACA,iCACA,gBACA,4CACA,YACA,oBACA,2BACA,UACA,6CAEE,cAIF,WAvBF,YAwBI,uBAIF,aACE,WACA,gCAIF,uBACE,UACA,6EAEE,YCrCN,uBACE,CADF,eACE,MACA,QACA,OACA,UACA,iCACA,4CACA,+DAIE,8CAGA,cAIF,WAlBF,YAmBI,mCAIF,gEAEI,8GAGA,kCAOJ,2BACE,4GAEE,gBASN,YACE,mBACA,gBACA,wBAGA,iBACE,UACA,qBACA,aACA,cACA,mBACA,sBACA,eACA,yBACA,2DAGA,UAEE,4CAIF,YACE,gCAIF,YACE,cACA,0CRmGF,+BQrGA,YAMI,wEAIF,aAEE,aACA,cACA,kBACA,qCRoEJ,qCQ/DA,YAII,8CAIF,YACE,oDAOA,oBACE,wCR8CN,qCQxCA,YAII,wBAMN,iBACE,aACA,eACA,wEAEE,6CAIF,UACE,8BACA,UACA,wEAEE,oBAEF,uDAGA,8BACE,uBAMN,WACE,cACA,mBACA,iBACA,gBACA,mBACA,mEAGA,UACE,+BACA,UACA,wEAEE,oBAEF,6EAGA,6BACE,yFAIF,SACE,wBACA,UACA,wEAEE,uBAEF,gDAKJ,iBACE,WACA,YACA,wBAKJ,YACE,qCRzCA,uBQwCF,aAKI,cACA,kBACA,iBACA,kCAGA,iBACE,oBACA,yCRrDJ,uBQwCF,kBAmBI,kCAGA,mBACE,aC/NR,+BACE,2CACA,cAGA,WALF,YAMI,wBAQF,aACE,cACA,sBAIF,YACE,mBACA,qBACA,yBACA,qCTwIA,qBS5IF,SAQI,wDAIF,UAEE,4BAIF,UACE,0CT2IF,2BS5IA,SAKI,kDAGA,YACE,uCAKJ,WACE,0CAGA,oBACE,4BAMN,WACE,iBACA,0CTiHF,2BSnHA,SAMI,uCAIF,UACE,gBACA,0CAGA,oBACE,uBAOR,iBACE,YACA,8BACA,eACA,gBACA,mBACA,wBAIF,YACE,cACA,2BAIF,iBACE,QACA,OACA,iBACA,eACA,iBACA,WACA,iBAKJ,gDACE,wBAGA,YACE,eACA,8BACA,cACA,mCAIF,sCACE,iFAGA,+BAEE,sBAMN,UACE,kBACA,gBACA,yCACA,iBACA,qCTiBE,qBStBJ,UASI,kCAKF,sCACE,mBAKJ,cACE,sBACA,uDAFF,eAMI,0BAIF,oBACE,aACA,cACA,kBACA,iCAGA,eACE,6BAIF,gBACE,oBACA,kBACA,OCvLN,6bACE,sbACA,0dACA,SAMF,eACE,gBACA,gBAGA,aACE,gBACA,gBACA,gBACA,uBACA,gCAGA,YACE,oCAGA,UACE,YACA,uFAOA,aAEE,aACA,cACA,kBACA,eAOR,QACE,UACA,gBACA,eAIF,eACE,6BAGA,eACE,uCAGA,mBACE,eACA,eAMN,aACE,kBACA,gBACA,uBACA,eACA,uBACA,wBACA,mCAGA,uCACE,qCAIF,+BACE,qCAIF,aACE,yCAIF,+BAEE,2CAIF,YACE,2DAGA,aACE,WACA,YACA,sCACA,CADA,6BACA,8BACA,mDAIF,YACE,iBAMN,YACE,0CVwDA,0CUjDA,iBAEE,MACA,QACA,OACA,UACA,aACA,sBACA,YACA,4CACA,gEAOA,eAEE,gBACA,iCAIF,iBACE,cACA,yBACA,wCACA,gBACA,mBACA,mBACA,sDACA,eACA,+CAGA,iBACE,UACA,WACA,cACA,aACA,cACA,aACA,yDAGA,WACE,aACA,sDAIF,aACE,WACA,YACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,+CAKJ,eACE,4CACA,iEAEE,qCACF,CADE,gCACF,CADE,4BACF,mBACA,4DAGA,YACE,+CAKJ,gCACE,4CACA,0CAIF,iBACE,UACA,WACA,cACA,aACA,cACA,oDAGA,WACE,aACA,gCAMN,MACE,gCAIF,SACE,6DACA,sDAGA,oBACE,gEAGA,mBACE,oBACA,sDAKJ,+BACE,uHAGA,+BAEE,gCAMN,iBACE,aACA,oBACA,8CAGA,iBACE,QACA,YACA,aACA,cACA,mBACA,cACA,iBACA,wDAGA,aACE,WACA,qDAIF,aACE,WACA,YACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,iDASJ,mBACE,mDAQF,eACE,6CAIF,eACE,6BACA,2DAGA,mBACE,qEAGA,oBACE,qBACA,mEAKJ,iBACE,6EAGA,kBACE,qBACA,2EAKJ,mBACE,qFAGA,oBACE,qBACA,mFAKJ,mBACE,6FAGA,oBACE,qBACA,oBAQV,4BACE,yBAIF,YACE,2BACA,UACA,2EAEE,mCAIF,2BACE,iCAKJ,uBACE,UACA,4EAEE,+CAIF,kCAEE,CAFF,0BAEE,2CV/NJ,0CUwOA,aACE,qBACA,qDAGA,mBACE,oBACA,2DAIF,UACE,yDAIF,YACE,mDAIF,YACE,iBAKJ,aACE,gBACA,iCACA,kDACA,gEV9SA,6CUsTF,aACE,qBACA,0BACA,wDAGA,mBACE,oBACA,8DAIF,UACE,4DAIF,YACE,sDAIF,YACE,sCVxTJ,6CUoUE,uBACE,iDAIF,YACE,yCV1UJ,QUvJJ,0DAweI,+CAME,uBACE,+CAIF,YACE,yBAKJ,YACE,uEAIF,aAEE,8CAIF,YACE,wBAIF,aACE,gBACA,mCAGA,eACE,sCAIF,YACE,gCAIF,aACE,+CAGA,aACE,UACA,oBACA,wBACA,4DAIF,SACE,eAMN,WACE,YACA,aACA,2BACA,yBAGA,UACE,yBACA,sBAIF,oBACE,WACA,YACA,uBACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,2JAIF,uBAEE,oFAQF,YAEE,6CAIF,YACE,qDAGA,aACE,UACA,mEAGA,YACE,4EAIF,aACE,gBACA,oBACA,wBACA,2DAKJ,mBACE,4CAMJ,aACE,sDAKJ,aACE,qBACA,oDACA,qEAGA,YACE,QCzoBR,4yBACE,YAMF,iBACE,qCXwJE,WWzJJ,eAKI,oBAIF,YACE,qBAIF,SACE,UACA,0CX2JA,oBW7JF,iBAMI,UACA,aACA,WACA,YACA,gBACA,4CACA,mBACA,wBACA,qDAEE,oBAEF,+BAGA,aACE,aACA,gEAIF,SACE,yCAEE,sCX6GN,oBW3IF,cAqCI,MACA,OACA,QACA,SACA,iCACA,eACA,0DAEE,+BAKF,OACE,aACA,gEAIF,UACE,YACA,UACA,8CAEE,2CXgGN,+DWzFA,mBAII,gEX8CF,+DWlDF,mBASI,gEXyCF,+DWlDF,mBAcI,oBAMN,kCAEE,CAFF,0BAEE,0CXmEA,kBWrEF,cAMI,MACA,UACA,UACA,WACA,YACA,yBACA,UACA,iHAEE,8DAMF,MACE,wBACA,UACA,+GAEE,wEAMF,OACE,aACA,kCAKJ,UACE,aACA,0BACA,sCXSJ,kBWnDF,iBAgDI,YACA,cACA,gBACA,sDACA,6BAGA,UACE,gEX1BF,6DW+BF,aAII,yCXdJ,6DWUA,aASI,mBAMN,iBACE,qCX1BA,iBWyBF,mBAKI,oBAKJ,iBACE,UACA,0BACA,uBACA,4CACA,8CAEE,6BAIF,yBACE,8CAIF,8BACE,CADF,sBACE,CALA,oCAIF,2BACE,CADF,sBACE,CALA,yCAIF,0BACE,CADF,sBACE,CALA,+BAIF,sBACE,8CAIF,uCAEE,CANA,oCAIF,uCAEE,CANA,yCAIF,uCAEE,CANA,kEAIF,uCAEE,8BAIF,YACE,0CX7CF,kBWiBF,UAiCI,cACA,gBACA,sCXtEF,kBWmCF,UAwCI,cACA,oBACA,cACA,gBACA,iCACA,oBACA,6BAGA,oBACE,oCAIF,gCACE,8CAIF,uCACE,CALA,oCAIF,uCACE,CALA,yCAIF,uCACE,CALA,+BAIF,uCACE,yBAIF,sCACE,8DAIF,gCACE,mBACA,4CACA,8BACA,yFAGA,uCAEE,CALF,+EAGA,uCAEE,CALF,oFAGA,uCAEE,CALF,wJAGA,uCAEE,mBAOR,iBACE,UACA,aACA,cACA,eACA,qCAEE,wBAIF,UACE,gCAIF,SACE,WACA,0CAGA,WACE,aACA,8CAGA,oBACE,0CXjIN,+BWsHA,SAiBI,WACA,0CAGA,WACE,aACA,gDAIF,YACE,sCXpKN,+BWwIA,mBAkCI,+CAGA,YACE,+BAMN,SACE,YACA,sBACA,UACA,wEAEE,oBAEF,wCAGA,aACE,WACA,0CX/KJ,6BWkKA,SAkBI,YACA,wCAGA,aACE,WACA,kGAKJ,kBAEE,UACA,uBACA,uGAGA,UACE,oBAOR,iBACE,UACA,WACA,gBACA,8BACA,0CXnNA,mBW8MF,UASI,SACA,sCX1OF,mBWgOF,UAeI,UACA,yBACA,+DAGA,kGVpYJ,UUuYM,yBAMN,WACE,gBACA,4CACA,mCAEA,CAFA,0BAEA,qCACA,CADA,gCACA,CADA,4BACA,mBACA,oEAGA,uBAVF,uBAWI,gEX7RA,uBWkRJ,aAgBI,yCX7QF,uBW6PF,aAqBI,sCXlRF,uBW6PF,YA0BI,qBACA,gEACA,mEAGA,eACE,8BAIF,qDACE,2CAIF,WACE,aACA,iDAIF,oDACE,uDAGA,0CACE,oBAQV,gCACE,sBACA,yBAGA,eACE,wCACA,iBACA,mBACA,sDACA,wBACA,qCXpUA,wBW8TF,mBAUI,mCAGA,oBACE,qBACA,0BAMN,QACE,UACA,gBACA,yBAIF,4DACE,qCAGA,eACE,yBAKJ,aACE,aACA,kCACA,wBACA,6DAGA,uDAEE,iDAIF,mBACE,iCAKJ,aACE,oBACA,gCACA,iBACA,UACA,eACA,8CAEE,wBAEF,qCXjYA,gCWuXF,mBAcI,2CAGA,oBACE,mBACA,8EAKJ,+BAEE,wDACA,yDAIF,YACE,qCAIF,WACE,4BAKJ,iBACE,gBACA,gBACA,qCXpaA,2BWiaF,mBAOI,sCAGA,oBACE,mBACA,gEAQF,eACE,gBACA,gBACA,gBACA,yBAMN,iBACE,OACA,aACA,cACA,aACA,wCACA,0CXnbA,wBW6aF,YAUI,iCAIF,oBACE,WACA,YACA,8BACA,gDACA,CADA,uCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,mCAIF,OACE,aACA,0CAGA,oBACE,0BAMN,aACE,gBACA,iBACA,gBACA,2BAIF,mBACE,gBACA,cACA,gBACA,wCACA,iBACA,gBACA,uBACA,4BACA,qBACA,0CXreA,0BW2dF,eAcI,qBACA,gEXjhBA,0BWkgBJ,eAoBI,qBACA,iCAIF,yBACE,6BACA,0BAKJ,aACE,iBACA,kBACA,wBAIF,+BACE,6BACA,aCtrBJ,uBACE,CADF,eACE,WACA,cACA,sBACA,cACA,SACA,iBACA,cAGA,YAVF,YAWI,2CZuKA,qBYhKA,cACE,MACA,cACA,UACA,cACA,cACA,YACA,4CACA,wBACA,yEAEE,gCAIF,cACE,aACA,oEAIF,sGXjBJ,8BWoBM,8EAGA,8BACE,8CAKJ,iBACE,MACA,QACA,SACA,OACA,SACA,8BACA,CADA,yBACA,CADA,qBACA,gBACA,yCZqGJ,YYhKJ,QAkEI,oBAGA,WACE,yBAKJ,YACE,QACA,qCZmFA,uBYrFF,QAMI,+BAGA,WACE,sCAIF,aACE,gDAIF,kBACE,0BAMN,cACE,gBACA,mCAEA,CAFA,0BAEA,qBAKA,gEACA,+BAGA,qDACE,4CAIF,WACE,aACA,kDAIF,oDACE,wDAGA,0CACE,0CZgDJ,YYtCF,cACE,MACA,UACA,QACA,SACA,iCACA,UACA,0DAEE,6CAKF,UACE,YACA,UACA,8CAEE,4CC/JR,GACE,QACE,MAEF,aACE,ED0JI,kCC/JR,GACE,QACE,MAEF,aACE,2CAKJ,GACE,0BACE,UACA,KAEF,SACE,MAEF,wBACE,UACA,EAfA,iCAKJ,GACE,0BACE,UACA,KAEF,SACE,MAEF,wBACE,UACA,aASJ,aACE,iBACA,gBACA,mBACA,mCAEA,CAFA,0BAEA,yBACA,mCAGA,UAEE,kBAIF,oBACE,aACA,cACA,sBACA,sBAGA,gBACE,kBACA,gCAGA,kBACE,oBACA,yCAKJ,iBACE,kBACA,mDAGA,kBACE,oBACA,mBACA,qBACA,wBAMN,oBACE,8BACA,kBACA,gBACA,gBACA,uBACA,sBACA,mBAIF,QACE,UACA,gBACA,gBACA,iBACA,qBACA,YACA,wCAGA,sDACE,CADF,8CACE,kBAKJ,UACE,4BAGA,WACE,uCAIF,sDACE,CADF,8CACE,0BAIF,cACE,YACA,sCAIF,YACE,UC/HN,UACE,cACA,iCACA,4CACA,kCACA,cAGA,SARF,YASI,2CdyKA,SclLJ,YAcI,iCAIF,mBACE,gBAIF,QACE,kBACA,UACA,mBACA,gBACA,gBACA,0BAGA,kBACE,oBACA,gBAKJ,oBACE,cACA,oBACA,mBACA,gBAKF,aACE,iBACA,gBACA,mCAEA,CAFA,0BAEA,WACA,wEAEE,kEAIF,aAGE,UACA,4CAKA,qBACE,4CADF,qBACE,4CADF,qBACE,4CADF,qBACE,4CADF,sBACE,4CADF,sBACE,4CADF,sBACE,4CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,+CAMJ,yBACE,UACA,6CAEE,OC5DR,+gBAEI,iyNAYF,iBACE,gBACA,gBACA,oCACA,iBACA,wBACA,+CACA,gCACA,oBACA,0EAEE,cAIF,4CAfF,eAgBI,kEAIF,gCACE,iBACA,iIAIF,YACE,6FAIF,kBACE,mFAIF,eACE,2FAIF,YACE,+EAIF,mBACE,mDAKJ,iBACE,2BACA,+BACA,gBACA,qCACA,gCACA,uEAGA,0BACE,+BACA,iCACA,iBACA,mFAIF,eACE,mEAIF,iBACE,WACA,WACA,YACA,yBCyIU,mDDvIV,CCuIU,0CDvIV,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,uFAGA,WACE,aACA,6DAMJ,cACE,gBACA,mBACA,6BACA,sBACA,gBACA,iGAKF,YACE,uDAcJ,oBAHO,+DAQP,oCACE,qBATK,+EAaL,wBAbK,mDAeH,CAfG,0CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,iLAdJ,oBAHO,yMAQP,mCACE,qBATK,yPAaL,wBAbK,uDAeH,CAfG,8CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,6GAdJ,oBAHO,6HAQP,mCACE,qBATK,6JAaL,wBAbK,mDAeH,CAfG,0CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,2KAdJ,oBAHO,mMAQP,mCACE,qBATK,mPAaL,wBAbK,kDAeH,CAfG,yCAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,2KAdJ,oBAHO,mMAQP,kCACE,qBATK,mPAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,yKAdJ,oBAHO,iMAQP,oCACE,qBATK,iPAaL,wBAbK,uDAeH,CAfG,8CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,yLAdJ,oBAHO,iNAQP,mCACE,qBATK,iQAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,+KAdJ,oBAHO,uMAQP,mCACE,qBATK,uPAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,mHAdJ,oBAHO,mIAQP,mCACE,qBATK,mKAaL,wBAbK,qDAeH,CAfG,4CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,qDAdJ,oBAHO,6DAQP,kCACE,qBATK,6EAaL,wBAbK,kDAeH,CAfG,yCAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,6DAdJ,oBAHO,qEAQP,oCACE,qBATK,qFAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,+GAdJ,oBAHO,+HAQP,qCACE,qBATK,+JAaL,wBAbK,oDAeH,CAfG,2CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,OExKN,6bACE,mCASA,yBACE,mBACA,mBACA,gCAIF,yBACE,oBACA,oBACA,uBAIF,uCACE,iBACA,0BAGA,aACE,0BAIF,sBACE,iCAGA,gCACE,oGAIF,uBAEE,UACA,uCAIF,YACE,+BAMN,oBACE,gCACA,YAEA,2BACA,8BACA,UACA,iEAEE,cAKF,8BAdF,+BAeI,wBACA,UACA,0CAIF,8BACE,qCAIF,+BACE,uCAIF,oBACE,YACA,aACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,qDAME,oBACE,yBCpGR,oBACE,kBACA,0CACA,UACA,qCAEE,cAIF,wBAVF,YAWI,oCAIF,kBACE,oBACA,8FAKJ,SAGE,qCAEE,6FAKJ,+BAGE,qBAOF,wBACE,mEAIF,yBAGE,2FAGA,aACE,mBACA,mBACA,WACA,uBAKJ,yBACE,+BAGA,aACE,oBACA,oBACA,WACA,6CAKJ,yBAEE,6DAGA,aACE,mBACA,mBACA,WACA,4BCpFJ,aACE,0CnB8KA,2BmB/KF,gBAKI,+BAIF,yBACE,CADF,sBACE,CADF,iBACE,2BACA,gBACA,kBACA,2ECbJ,kCAGE,CAHF,0BAGE,wBAIF,4CACE,wBAIF,4CACE,6BAIF,qCACE,qCAGA,aACE,oCAIF,aACE,2BAKJ,aACE,aACA,oBACA,mBACA,cACA,gBACA,wCAGA,eACE,uCAIF,kBACE,OClDN,mbACE,qBASA,aAGE,cACA,iBACA,0CAGA,uBACE,iCAIF,gBACE,gBACA,yCAMA,mBACE,4BAKJ,aACE,WACA,qBAKJ,aAGE,gBACA,gCACA,6BACA,8BACA,eACA,+BAGA,iCACE,yCAIF,YACE,wCACA,4BAIF,iBACE,UACA,YACA,WACA,YACA,8BACA,0CACA,CADA,iCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,uBACA,2BACA,WACA,sCAGA,aACE,WACA,yBACA,6CAKJ,YACE,gECvFJ,oBAGE,eACA,wBACA,4EAGA,aACE,gBACA,kBACA,8BCZJ,sCAEE,eAGF,yCACE,uIAGF,oCASE,4EAGF,qCAKE,0FAGF,oCAME,0FAGF,qCAME,8BAGF,kCAEE,8CAGF,sCAGE,6DAGF,sCAIE,6DAGF,qCAIE,0FAGF,qCAME,4EAGF,sCAKE,yHAGF,qCAQE,+BAGF,iBAEE,iBACA,oBACA,gBAGF,4CACE,gBAGF,4CACE,iBAIF,aACE,yBACA,yBACA,yCACA,mCAIF,uBACE,CADF,eACE,qBACA,WACA,4BACA,4BACA,4BACA,wCACA,yCACA,iEACA,2BACA,yBACA,CADA,qBACA,CADA,oBACA,CADA,gBACA,iBASJ,iBACE,gBACA,0CAIA,aAEE,UACA,oBAKF,YACE,qBAKF,QACE,0BAKF,oCACE,gBACA,gBACA,yCACA,yBACA,CADA,qBACA,CADA,oBACA,CADA,gBACA,4BAIF,2BACE,iEACA,gCAGA,uCACE,iBACA,uBAKJ,MACE,gBACA,6BAUF,YACE,cACA,oBACA,kCAGA,eACE,0CvBlCF,uBuB0CA,kBACE,6BAGA,gBACE,gBACA,6BAIF,eACE,6BAKJ,kBACE,gBACA,kCAGA,gBACE,gBACA,6DC7OJ,iBAEE,SACA,cACA,gCACA,+BACA,wBAIF,cACE,wCACA,oCAqDE,kBACE,YAlDgB,yCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,qCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,yCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,oCAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,qCAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,mCA+DlB,iBACE,YAPgB,yCAMlB,iBACE,YAPgB,qCAMlB,iBACE,YAPgB,6BC5ExB,YACE,SACA,WACA,2DACA,cAGA,4BAPF,aAQI,cACA,0JAKF,QAGE,wKAGA,wBACE,0BACA,yCAKJ,QACE,yBAKJ,iBACE,aACA,eACA,aACA,oBACA,+BAMA,iBACE,QACA,SACA,UACA,6CAGA,+BACE,uCACA,6DAGA,aACE,2CAKJ,kBACE,yDAIF,YACE,wCACA,+BAKJ,SACE,WACA,gCACA,wCACA,gBACA,iBACA,sCACA,eACA,uBACA,qCAGA,+BACE,OC1FR,yWACE,mXAGA,6BAWA,iBACE,qBACA,6CAIA,iBACE,UACA,UACA,uDAGA,UACE,aACA,gDAMN,UACE,UACA,0CAIF,iBACE,UACA,YACA,aACA,cACA,sDACA,2CACA,CADA,kCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,oDAGA,YACE,aACA,kEAKJ,wBV6Ve,oDU3Vb,CV2Va,2CU3Vb,C","file":"assets/stylesheets/main.3b61ea93.min.css","sourcesContent":["html{box-sizing:border-box;text-size-adjust:none}*,*::before,*::after{box-sizing:inherit}body{margin:0}a,button,label,input{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{display:block;box-sizing:content-box;height:.05rem;padding:0;overflow:visible;border:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:separate;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{margin:0;padding:0;font-size:inherit;background:transparent;border:0}input{border:0;outline:none}:root{--md-default-fg-color: hsla(0, 0%, 0%, 0.87);--md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);--md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);--md-default-bg-color: hsla(0, 0%, 100%, 1);--md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}:root>*{--md-code-fg-color: hsla(200, 18%, 26%, 1);--md-code-bg-color: hsla(0, 0%, 96%, 1);--md-code-hl-color: hsla(60, 100%, 50%, 0.5);--md-code-hl-number-color: hsla(0, 67%, 50%, 1);--md-code-hl-special-color: hsla(340, 83%, 47%, 1);--md-code-hl-function-color: hsla(291, 45%, 50%, 1);--md-code-hl-constant-color: hsla(250, 63%, 60%, 1);--md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);--md-code-hl-string-color: hsla(150, 63%, 30%, 1);--md-code-hl-name-color: var(--md-code-fg-color);--md-code-hl-operator-color: var(--md-default-fg-color--light);--md-code-hl-punctuation-color: var(--md-default-fg-color--light);--md-code-hl-comment-color: var(--md-default-fg-color--light);--md-code-hl-generic-color: var(--md-default-fg-color--light);--md-code-hl-variable-color: var(--md-default-fg-color--light);--md-typeset-color: var(--md-default-fg-color);--md-typeset-a-color: var(--md-primary-fg-color);--md-typeset-mark-color: hsla(60, 100%, 50%, 0.5);--md-typeset-del-color: hsla(6, 90%, 60%, 0.15);--md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);--md-typeset-kbd-color: hsla(0, 0%, 98%, 1);--md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);--md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);--md-admonition-fg-color: var(--md-default-fg-color);--md-admonition-bg-color: var(--md-default-bg-color);--md-footer-fg-color: hsla(0, 0%, 100%, 1);--md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-footer-bg-color: hsla(0, 0%, 0%, 0.87);--md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32)}.md-icon svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,input{color:var(--md-typeset-color);font-feature-settings:\"kern\",\"liga\";font-family:-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,pre,kbd{color:var(--md-typeset-color);font-feature-settings:\"kern\";font-family:SFMono-Regular,Consolas,Menlo,monospace}:root{--md-typeset-table--ascending: svg-load(\"@mdi/svg/svg/arrow-down.svg\");--md-typeset-table--descending: svg-load(\"@mdi/svg/svg/arrow-up.svg\")}.md-typeset{font-size:.8rem;line-height:1.6;color-adjust:exact}@media print{.md-typeset{font-size:.68rem}}.md-typeset p,.md-typeset ul,.md-typeset ol,.md-typeset dl,.md-typeset blockquote{margin:1em 0}.md-typeset h1{margin:0 0 1.25em;color:var(--md-default-fg-color--light);font-weight:300;font-size:2em;line-height:1.3;letter-spacing:-0.01em}.md-typeset h2{margin:1.6em 0 .64em;font-weight:300;font-size:1.5625em;line-height:1.4;letter-spacing:-0.01em}.md-typeset h3{margin:1.6em 0 .8em;font-weight:400;font-size:1.25em;line-height:1.5;letter-spacing:-0.01em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{margin:1em 0;font-weight:700;letter-spacing:-0.01em}.md-typeset h5,.md-typeset h6{margin:1.25em 0;color:var(--md-default-fg-color--light);font-weight:700;font-size:.8em;letter-spacing:-0.01em}.md-typeset h5{text-transform:uppercase}.md-typeset hr{margin:1.5em 0;border-bottom:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a::before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset code,.md-typeset pre,.md-typeset kbd{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset pre,.md-typeset kbd{white-space:pre-wrap}}.md-typeset code{padding:0 .2941176471em;font-size:.85em;word-break:break-word;background-color:var(--md-code-bg-color);border-radius:.1rem;box-decoration-break:clone}.md-typeset code:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset h1 code,.md-typeset h2 code,.md-typeset h3 code,.md-typeset h4 code,.md-typeset h5 code,.md-typeset h6 code{margin:initial;padding:initial;background-color:transparent;box-shadow:none}.md-typeset a>code{color:currentColor}.md-typeset pre{position:relative;margin:1em 0;line-height:1.4}.md-typeset pre>code{display:block;margin:0;padding:.7720588235em 1.1764705882em;overflow:auto;word-break:normal;box-shadow:none;box-decoration-break:slice;touch-action:auto;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{width:.2rem;height:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 44.9375em){.md-typeset>pre{margin:1em -0.8rem}.md-typeset>pre code{border-radius:0}}.md-typeset kbd{display:inline-block;padding:0 .6666666667em;color:var(--md-default-fg-color);font-size:.75em;vertical-align:text-top;word-break:break-word;background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -0.1rem .2rem var(--md-typeset-kbd-accent-color) inset}.md-typeset mark{color:inherit;word-break:break-word;background-color:var(--md-typeset-mark-color);box-decoration-break:clone}.md-typeset abbr{text-decoration:none;border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help}@media(hover: none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:focus::after,.md-typeset abbr[title]:hover::after{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:absolute;left:0;display:inline-block;width:auto;min-width:max-content;max-width:80%;margin-top:2em;padding:.2rem .3rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border-radius:.1rem;content:attr(title)}}.md-typeset small{opacity:.75}.md-typeset sup,.md-typeset sub{margin-left:.078125em}[dir=rtl] .md-typeset sup,[dir=rtl] .md-typeset sub{margin-right:.078125em;margin-left:initial}.md-typeset blockquote{padding-left:.6rem;color:var(--md-default-fg-color--light);border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{padding-right:.6rem;padding-left:initial;border-right:.2rem solid var(--md-default-fg-color--lighter);border-left:initial}.md-typeset ul{list-style-type:disc}.md-typeset ul,.md-typeset ol{margin-left:.625em;padding:0}[dir=rtl] .md-typeset ul,[dir=rtl] .md-typeset ol{margin-right:.625em;margin-left:initial}.md-typeset ul ol,.md-typeset ol ol{list-style-type:lower-alpha}.md-typeset ul ol ol,.md-typeset ol ol ol{list-style-type:lower-roman}.md-typeset ul li,.md-typeset ol li{margin-bottom:.5em;margin-left:1.25em}[dir=rtl] .md-typeset ul li,[dir=rtl] .md-typeset ol li{margin-right:1.25em;margin-left:initial}.md-typeset ul li p,.md-typeset ul li blockquote,.md-typeset ol li p,.md-typeset ol li blockquote{margin:.5em 0}.md-typeset ul li:last-child,.md-typeset ol li:last-child{margin-bottom:0}.md-typeset ul li ul,.md-typeset ul li ol,.md-typeset ol li ul,.md-typeset ol li ol{margin:.5em 0 .5em .625em}[dir=rtl] .md-typeset ul li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ol li ol{margin-right:.625em;margin-left:initial}.md-typeset dd{margin:1em 0 1.5em 1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em;margin-left:initial}.md-typeset img,.md-typeset svg{max-width:100%;height:auto}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em;margin-left:0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em;margin-right:0}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset figure{width:fit-content;max-width:100%;margin:0 auto;text-align:center}.md-typeset figure img{display:block}.md-typeset figcaption{max-width:24rem;margin:1em auto 2em;font-style:italic}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){display:inline-block;max-width:100%;overflow:auto;font-size:.64rem;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) th>*:first-child,.md-typeset table:not([class]) td>*:first-child{margin-top:0}.md-typeset table:not([class]) th>*:last-child,.md-typeset table:not([class]) td>*:last-child{margin-bottom:0}.md-typeset table:not([class]) th:not([align]),.md-typeset table:not([class]) td:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) th:not([align]),[dir=rtl] .md-typeset table:not([class]) td:not([align]){text-align:right}.md-typeset table:not([class]) th{min-width:5rem;padding:.9375em 1.25em;color:var(--md-default-bg-color);vertical-align:top;background-color:var(--md-default-fg-color--light)}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{padding:.9375em 1.25em;vertical-align:top;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset table:not([class]) tr{transition:background-color 125ms}.md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) tr:first-child td{border-top:0}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}.md-typeset table th[role=columnheader]::after{display:inline-block;width:1.2em;height:1.2em;margin-left:.5em;vertical-align:sub;mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-typeset table th[role=columnheader][aria-sort=ascending]::after{background-color:currentColor;mask-image:var(--md-typeset-table--ascending)}.md-typeset table th[role=columnheader][aria-sort=descending]::after{background-color:currentColor;mask-image:var(--md-typeset-table--descending)}.md-typeset__scrollwrap{margin:1em -0.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;width:100%;margin:0;overflow:hidden}html{height:100%;overflow-x:hidden;font-size:125%}@media screen and (min-width: 100em){html{font-size:137.5%}}@media screen and (min-width: 125em){html{font-size:150%}}body{position:relative;display:flex;flex-direction:column;width:100%;min-height:100%;font-size:.5rem;background-color:var(--md-default-bg-color)}@media print{body{display:block}}@media screen and (max-width: 59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{max-width:61rem;margin-right:auto;margin-left:auto}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.md-toggle{display:none}.md-skip{position:fixed;z-index:-1;margin:.5rem;padding:.3rem .5rem;color:var(--md-default-bg-color);font-size:.64rem;background-color:var(--md-default-fg-color);border-radius:.1rem;transform:translateY(0.4rem);opacity:0}.md-skip:focus{z-index:10;transform:translateY(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 175ms 75ms}@page{margin:25mm}.md-announce{overflow:auto;background-color:var(--md-footer-bg-color)}@media print{.md-announce{display:none}}.md-announce__inner{margin:.6rem auto;padding:0 .8rem;color:var(--md-footer-fg-color);font-size:.7rem}.md-typeset .md-button{display:inline-block;padding:.625em 2em;color:var(--md-primary-fg-color);font-weight:700;border:.1rem solid currentColor;border-radius:.1rem;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{color:var(--md-accent-bg-color);background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}:root{--md-clipboard-icon: svg-load(\"@mdi/svg/svg/content-copy.svg\")}.md-clipboard{position:absolute;top:.5em;right:.5em;z-index:1;width:1.5em;height:1.5em;color:var(--md-default-fg-color--lightest);border-radius:.1rem;cursor:pointer;transition:color 250ms}@media print{.md-clipboard{display:none}}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard::after{display:block;width:1.125em;height:1.125em;margin:0 auto;background-color:currentColor;mask-image:var(--md-clipboard-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-content{flex-grow:1;overflow:hidden;scroll-padding-top:51.2rem}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width: 76.25em){.md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem;margin-left:.8rem}.md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:.8rem;margin-left:1.2rem}}.md-content__inner::before{display:block;height:.4rem;content:\"\"}.md-content__inner>:last-child{margin-bottom:0}.md-content__button{float:right;margin:.4rem 0;margin-left:.4rem;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left;margin-right:.4rem;margin-left:initial}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}.md-dialog{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:fixed;right:.8rem;bottom:.8rem;left:initial;z-index:2;display:block;min-width:11.1rem;padding:.4rem .6rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border:none;border-radius:.1rem;transform:translateY(100%);opacity:0;transition:transform 0ms 400ms,opacity 400ms}@media print{.md-dialog{display:none}}[dir=rtl] .md-dialog{right:initial;left:.8rem}.md-dialog[data-md-state=open]{transform:translateY(0);opacity:1;transition:transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),opacity 400ms}.md-header{position:sticky;top:0;right:0;left:0;z-index:2;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem rgba(0,0,0,0),0 .2rem .4rem rgba(0,0,0,0);transition:color 250ms,background-color 250ms}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header-nav{display:flex;align-items:center;padding:0 .2rem}.md-header-nav__button{position:relative;z-index:1;display:inline-block;margin:.2rem;padding:.4rem;color:currentColor;vertical-align:middle;cursor:pointer;transition:opacity 250ms}.md-header-nav__button:focus,.md-header-nav__button:hover{opacity:.7}.md-header-nav__button:not(.focus-visible){outline:none}.md-header-nav__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width: 76.1875em){.md-header-nav__button.md-logo{display:none}}.md-header-nav__button.md-logo img,.md-header-nav__button.md-logo svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}@media screen and (min-width: 60em){.md-header-nav__button[for=__search]{display:none}}.no-js .md-header-nav__button[for=__search]{display:none}[dir=rtl] .md-header-nav__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width: 76.25em){.md-header-nav__button[for=__drawer]{display:none}}.md-header-nav__topic{position:absolute;display:flex;max-width:100%;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms}.md-header-nav__topic+.md-header-nav__topic{z-index:-1;transform:translateX(1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__topic+.md-header-nav__topic{transform:translateX(-1.25rem)}.md-header-nav__title{flex-grow:1;height:2.4rem;margin-right:.4rem;margin-left:1rem;font-size:.9rem;line-height:2.4rem}.md-header-nav__title[data-md-state=active] .md-header-nav__topic{z-index:-1;transform:translateX(-1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__title[data-md-state=active] .md-header-nav__topic{transform:translateX(1.25rem)}.md-header-nav__title[data-md-state=active] .md-header-nav__topic+.md-header-nav__topic{z-index:0;transform:translateX(0);opacity:1;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:initial}.md-header-nav__title>.md-header-nav__ellipsis{position:relative;width:100%;height:100%}.md-header-nav__source{display:none}@media screen and (min-width: 60em){.md-header-nav__source{display:block;width:11.7rem;max-width:11.7rem;margin-left:1rem}[dir=rtl] .md-header-nav__source{margin-right:1rem;margin-left:initial}}@media screen and (min-width: 76.25em){.md-header-nav__source{margin-left:1.4rem}[dir=rtl] .md-header-nav__source{margin-right:1.4rem}}.md-footer{color:var(--md-footer-fg-color);background-color:var(--md-footer-bg-color)}@media print{.md-footer{display:none}}.md-footer-nav__inner{padding:.2rem;overflow:auto}.md-footer-nav__link{display:flex;padding-top:1.4rem;padding-bottom:.4rem;transition:opacity 250ms}@media screen and (min-width: 45em){.md-footer-nav__link{width:50%}}.md-footer-nav__link:focus,.md-footer-nav__link:hover{opacity:.7}.md-footer-nav__link--prev{float:left}@media screen and (max-width: 44.9375em){.md-footer-nav__link--prev{width:25%}.md-footer-nav__link--prev .md-footer-nav__title{display:none}}[dir=rtl] .md-footer-nav__link--prev{float:right}[dir=rtl] .md-footer-nav__link--prev svg{transform:scaleX(-1)}.md-footer-nav__link--next{float:right;text-align:right}@media screen and (max-width: 44.9375em){.md-footer-nav__link--next{width:75%}}[dir=rtl] .md-footer-nav__link--next{float:left;text-align:left}[dir=rtl] .md-footer-nav__link--next svg{transform:scaleX(-1)}.md-footer-nav__title{position:relative;flex-grow:1;max-width:calc(100% - 2.4rem);padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-footer-nav__button{margin:.2rem;padding:.4rem}.md-footer-nav__direction{position:absolute;right:0;left:0;margin-top:-1rem;padding:0 1rem;font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-footer-copyright{width:100%;margin:auto .6rem;padding:.4rem 0;color:var(--md-footer-fg-color--lighter);font-size:.64rem}@media screen and (min-width: 45em){.md-footer-copyright{width:auto}}.md-footer-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-footer-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width: 45em){.md-footer-social{padding:.6rem 0}}.md-footer-social__link{display:inline-block;width:1.6rem;height:1.6rem;text-align:center}.md-footer-social__link::before{line-height:1.9}.md-footer-social__link svg{max-height:.8rem;vertical-align:-25%;fill:currentColor}:root{--md-nav-icon--prev: svg-load(\"@mdi/svg/svg/arrow-left.svg\");--md-nav-icon--next: svg-load(\"@mdi/svg/svg/chevron-right.svg\");--md-toc-icon: svg-load(\"@mdi/svg/svg/table-of-contents.svg\")}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;padding:0 .6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{width:auto;height:100%}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{display:block;width:2.4rem;height:2.4rem;fill:currentColor}.md-nav__list{margin:0;padding:0;list-style:none}.md-nav__item{padding:0 .6rem}.md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-right:.6rem;padding-left:0}.md-nav__link{display:block;margin-top:.625em;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:color 125ms;scroll-snap-align:start}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item--nested>.md-nav__link{color:inherit}.md-nav__link:focus,.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{display:block;width:100%;height:100%;mask-image:var(--md-toc-icon);background-color:currentColor}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__source{display:none}@media screen and (max-width: 76.1875em){.md-nav--primary,.md-nav--primary .md-nav{position:absolute;top:0;right:0;left:0;z-index:1;display:flex;flex-direction:column;height:100%;background-color:var(--md-default-bg-color)}.md-nav--primary .md-nav__title,.md-nav--primary .md-nav__item{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{position:relative;height:5.6rem;padding:3rem .8rem .2rem;color:var(--md-default-fg-color--light);font-weight:400;line-height:2.4rem;white-space:nowrap;background-color:var(--md-default-fg-color--lightest);cursor:pointer}.md-nav--primary .md-nav__title .md-nav__icon{position:absolute;top:.4rem;left:.4rem;display:block;width:1.2rem;height:1.2rem;margin:.2rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem;left:initial}.md-nav--primary .md-nav__title .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-nav-icon--prev);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-nav--primary .md-nav__title~.md-nav__list{overflow-y:auto;background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color)}.md-nav--primary .md-nav__title .md-logo{position:absolute;top:.2rem;left:.2rem;display:block;margin:.2rem;padding:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-logo{right:.2rem;left:initial}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{padding:0;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{position:relative;margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link .md-nav__icon{position:absolute;top:50%;right:.6rem;width:1.2rem;height:1.2rem;margin-top:-0.6rem;color:inherit;font-size:1.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{right:initial;left:.6rem}.md-nav--primary .md-nav__link .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-nav-icon--next);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-nav--primary .md-nav__icon::after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav__link{position:static}.md-nav--primary .md-nav--secondary .md-nav{position:static;background-color:transparent}.md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem;padding-left:initial}.md-nav--secondary{background-color:transparent}.md-nav__toggle~.md-nav{display:flex;transform:translateX(100%);opacity:0;transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{transform:translateX(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{backface-visibility:hidden}}@media screen and (max-width: 59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:block;padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{content:\"\"}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{display:block;padding:0 .2rem;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color--dark)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:block;padding-right:2.4rem;scroll-snap-align:initial}[dir=rtl] .md-nav--integrated .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--integrated .md-nav__link[for=__toc] .md-icon::after{content:\"\"}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width: 60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width: 76.25em){.md-nav{transition:max-height 250ms cubic-bezier(0.86, 0, 0.07, 1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__title{display:block;padding:0;pointer-events:none;scroll-snap-align:start}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{float:right;width:.9rem;height:.9rem;transition:transform 250ms}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon::after{display:inline-block;width:100%;height:100%;vertical-align:-0.1rem;background-color:currentColor;mask-image:var(--md-nav-icon--next);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav>.md-nav__title{display:block;padding:0 .6rem;pointer-events:none;scroll-snap-align:start}.md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav__item{padding-right:.6rem}.md-nav--lifted .md-nav[data-md-level=\"1\"]{display:block}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:block;margin-bottom:1.25em;border-left:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav>.md-nav__title{display:none}}:root{--md-search-result-icon: svg-load(\"@mdi/svg/svg/file-search-outline.svg\")}.md-search{position:relative}@media screen and (min-width: 60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{z-index:1;opacity:0}@media screen and (max-width: 59.9375em){.md-search__overlay{position:absolute;top:.2rem;left:-2.2rem;width:2rem;height:2rem;overflow:hidden;background-color:var(--md-default-bg-color);border-radius:1rem;transform-origin:center;transition:transform 300ms 100ms,opacity 200ms 200ms;pointer-events:none}[dir=rtl] .md-search__overlay{right:-2.2rem;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform 400ms,opacity 100ms}}@media screen and (min-width: 60em){.md-search__overlay{position:fixed;top:0;left:0;width:0;height:0;background-color:rgba(0,0,0,.54);cursor:pointer;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[dir=rtl] .md-search__overlay{right:0;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@media screen and (max-width: 29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width: 30em)and (max-width: 44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width: 45em)and (max-width: 59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{backface-visibility:hidden}@media screen and (max-width: 59.9375em){.md-search__inner{position:fixed;top:0;left:100%;z-index:2;width:100%;height:100%;transform:translateX(5%);opacity:0;transition:right 0ms 300ms,left 0ms 300ms,transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),opacity 150ms 150ms}[data-md-toggle=search]:checked~.md-header .md-search__inner{left:0;transform:translateX(0);opacity:1;transition:right 0ms 0ms,left 0ms 0ms,transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms 150ms}[dir=rtl] [data-md-toggle=search]:checked~.md-header .md-search__inner{right:0;left:initial}html [dir=rtl] .md-search__inner{right:100%;left:initial;transform:translateX(-5%)}}@media screen and (min-width: 60em){.md-search__inner{position:relative;float:right;width:11.7rem;padding:.1rem 0;transition:width 250ms cubic-bezier(0.1, 0.7, 0.1, 1)}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width: 60em)and (max-width: 76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width: 76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{position:relative}@media screen and (min-width: 60em){.md-search__form{border-radius:.1rem}}.md-search__input{position:relative;z-index:2;padding:0 2.2rem 0 3.6rem;text-overflow:ellipsis;background-color:var(--md-default-bg-color);transition:color 250ms,background-color 250ms}[dir=rtl] .md-search__input{padding:0 3.6rem 0 2.2rem}.md-search__input::placeholder{transition:color 250ms}.md-search__input~.md-search__icon,.md-search__input::placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width: 59.9375em){.md-search__input{width:100%;height:2.4rem;font-size:.9rem}}@media screen and (min-width: 60em){.md-search__input{width:100%;height:1.8rem;padding-left:2.2rem;color:inherit;font-size:.8rem;background-color:rgba(0,0,0,.26);border-radius:.1rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input:hover{background-color:rgba(255,255,255,.12)}[data-md-toggle=search]:checked~.md-header .md-search__input{color:var(--md-default-fg-color);text-overflow:clip;background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{position:absolute;z-index:2;width:1.2rem;height:1.2rem;cursor:pointer;transition:color 250ms,opacity 250ms}.md-search__icon:hover{opacity:.7}.md-search__icon[for=__search]{top:.3rem;left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem;left:initial}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width: 59.9375em){.md-search__icon[for=__search]{top:.6rem;left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem;left:initial}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width: 60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}.md-search__icon[type=reset]{top:.3rem;right:.5rem;transform:scale(0.75);opacity:0;transition:transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:none}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.5rem}@media screen and (max-width: 59.9375em){.md-search__icon[type=reset]{top:.6rem;right:.8rem}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]{transform:scale(1);opacity:1;pointer-events:initial}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]:hover{opacity:.7}.md-search__output{position:absolute;z-index:1;width:100%;overflow:hidden;border-radius:0 0 .1rem .1rem}@media screen and (max-width: 59.9375em){.md-search__output{top:2.4rem;bottom:0}}@media screen and (min-width: 60em){.md-search__output{top:1.9rem;opacity:0;transition:opacity 400ms}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12),0 3px 5px -1px rgba(0,0,0,.4);opacity:1}}.md-search__scrollwrap{height:100%;overflow-y:auto;background-color:var(--md-default-bg-color);backface-visibility:hidden;scroll-snap-type:y mandatory;touch-action:pan-y}@media(max-resolution: 1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width: 76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width: 60em){.md-search__scrollwrap{max-height:0;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{padding:0 .8rem;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;background-color:var(--md-default-fg-color--lightest);scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem;padding-left:initial}}.md-search-result__list{margin:0;padding:0;list-style:none}.md-search-result__item{box-shadow:0 -0.05rem 0 var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;transition:background-color 250ms;scroll-snap-align:start}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{display:block;padding:.75em .8rem;color:var(--md-typeset-a-color);font-size:.64rem;outline:0;cursor:pointer;transition:color 250ms,background-color 250ms;scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__more summary:focus,.md-search-result__more summary:hover{color:var(--md-accent-fg-color);background-color:var(--md-accent-fg-color--transparent)}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{position:relative;padding:0 .8rem;overflow:hidden}@media screen and (min-width: 60em){.md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__article--document .md-search-result__title{margin:.55rem 0;font-weight:400;font-size:.8rem;line-height:1.4}.md-search-result__icon{position:absolute;left:0;width:1.2rem;height:1.2rem;margin:.5rem;color:var(--md-default-fg-color--light)}@media screen and (max-width: 59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon::after{display:inline-block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-search-result-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-search-result__icon{right:0;left:initial}[dir=rtl] .md-search-result__icon::after{transform:scaleX(-1)}.md-search-result__title{margin:.5em 0;font-weight:700;font-size:.64rem;line-height:1.6}.md-search-result__teaser{display:-webkit-box;max-height:2rem;margin:.5em 0;overflow:hidden;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6;text-overflow:ellipsis;-webkit-box-orient:vertical;-webkit-line-clamp:2}@media screen and (max-width: 44.9375em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}.md-search-result__teaser mark{text-decoration:underline;background-color:transparent}.md-search-result__terms{margin:.5em 0;font-size:.64rem;font-style:italic}.md-search-result mark{color:var(--md-accent-fg-color);background-color:transparent}.md-sidebar{position:sticky;top:2.4rem;flex-shrink:0;align-self:flex-start;width:12.1rem;height:0;padding:1.2rem 0}@media print{.md-sidebar{display:none}}@media screen and (max-width: 76.1875em){.md-sidebar--primary{position:fixed;top:0;left:-12.1rem;z-index:3;display:block;width:12.1rem;height:100%;background-color:var(--md-default-bg-color);transform:translateX(0);transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 250ms}[dir=rtl] .md-sidebar--primary{right:-12.1rem;left:initial}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.4);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{position:absolute;top:0;right:0;bottom:0;left:0;margin:0;scroll-snap-type:none;overflow:hidden}}@media screen and (min-width: 76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width: 60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{margin:0 .2rem;overflow-y:auto;backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 76.1875em){.md-overlay{position:fixed;top:0;z-index:3;width:0;height:0;background-color:rgba(0,0,0,.54);opacity:0;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[data-md-toggle=drawer]:checked~.md-overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}.md-source{display:block;font-size:.65rem;line-height:1.2;white-space:nowrap;backface-visibility:hidden;transition:opacity 250ms}.md-source:focus,.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;width:2.4rem;height:2.4rem;vertical-align:middle}.md-source__icon svg{margin-top:.6rem;margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem;margin-left:initial}.md-source__icon+.md-source__repository{margin-left:-2rem;padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem;margin-left:initial;padding-right:2rem;padding-left:initial}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);margin-left:.6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{margin:0;padding:0;overflow:hidden;font-weight:700;font-size:.55rem;list-style-type:none;opacity:.75}[data-md-state=done] .md-source__facts{animation:md-source__facts--done 250ms ease-in}.md-source__fact{float:left}[dir=rtl] .md-source__fact{float:right}[data-md-state=done] .md-source__fact{animation:md-source__fact--done 400ms ease-out}.md-source__fact::before{margin:0 .1rem;content:\"·\"}.md-source__fact:first-child::before{display:none}.md-tabs{width:100%;overflow:auto;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);transition:background-color 250ms}@media print{.md-tabs{display:none}}@media screen and (max-width: 76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}.md-tabs__list{margin:0;margin-left:.2rem;padding:0;white-space:nowrap;list-style:none;contain:content}[dir=rtl] .md-tabs__list{margin-right:.2rem;margin-left:initial}.md-tabs__item{display:inline-block;height:2.4rem;padding-right:.6rem;padding-left:.6rem}.md-tabs__link{display:block;margin-top:.8rem;font-size:.7rem;backface-visibility:hidden;opacity:.7;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 250ms}.md-tabs__link--active,.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:100ms}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:120ms}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:140ms}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:160ms}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:180ms}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:200ms}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:220ms}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:240ms}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:260ms}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:280ms}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:300ms}.md-tabs[data-md-state=hidden] .md-tabs__link{transform:translateY(50%);opacity:0;transition:transform 0ms 100ms,opacity 100ms}:root{--md-admonition-icon--note: svg-load( \"@mdi/svg/svg/pencil.svg\" );--md-admonition-icon--abstract: svg-load( \"@mdi/svg/svg/text-subject.svg\" );--md-admonition-icon--info: svg-load( \"@mdi/svg/svg/information.svg\" );--md-admonition-icon--tip: svg-load( \"@mdi/svg/svg/fire.svg\" );--md-admonition-icon--success: svg-load( \"@mdi/svg/svg/check-circle.svg\" );--md-admonition-icon--question: svg-load( \"@mdi/svg/svg/help-circle.svg\" );--md-admonition-icon--warning: svg-load( \"@mdi/svg/svg/alert.svg\" );--md-admonition-icon--failure: svg-load( \"@mdi/svg/svg/close-circle.svg\" );--md-admonition-icon--danger: svg-load( \"@mdi/svg/svg/flash-circle.svg\" );--md-admonition-icon--bug: svg-load( \"@mdi/svg/svg/bug.svg\" );--md-admonition-icon--example: svg-load( \"@mdi/svg/svg/format-list-numbered.svg\" );--md-admonition-icon--quote: svg-load( \"@mdi/svg/svg/format-quote-close.svg\" )}.md-typeset .admonition,.md-typeset details{margin:1.5625em 0;padding:0 .6rem;overflow:hidden;color:var(--md-admonition-fg-color);font-size:.64rem;page-break-inside:avoid;background-color:var(--md-admonition-bg-color);border-left:.2rem solid #448aff;border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 .025rem .05rem rgba(0,0,0,.05)}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}[dir=rtl] .md-typeset .admonition,[dir=rtl] .md-typeset details{border-right:.2rem solid #448aff;border-left:none}.md-typeset .admonition .admonition,.md-typeset details .admonition,.md-typeset .admonition details,.md-typeset details details{margin:1em 0}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -0.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}.md-typeset .admonition-title,.md-typeset summary{position:relative;margin:0 -0.6rem 0 -0.8rem;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(68,138,255,.1);border-left:.2rem solid #448aff}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{margin:0 -0.8rem 0 -0.6rem;padding:.4rem 2rem .4rem .6rem;border-right:.2rem solid #448aff;border-left:none}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}.md-typeset .admonition-title::before,.md-typeset summary::before{position:absolute;left:.6rem;width:1rem;height:1rem;background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .admonition-title::before,[dir=rtl] .md-typeset summary::before{right:.6rem;left:initial}.md-typeset .admonition-title code,.md-typeset summary code{margin:initial;padding:initial;color:currentColor;background-color:transparent;border-radius:initial;box-shadow:none}.md-typeset .admonition-title+.tabbed-set:last-child,.md-typeset summary+.tabbed-set:last-child{margin-top:0}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:rgba(68,138,255,.1);border-color:#448aff}.md-typeset .note>.admonition-title::before,.md-typeset .note>summary::before{background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.abstract,.md-typeset details.abstract,.md-typeset .admonition.tldr,.md-typeset details.tldr,.md-typeset .admonition.summary,.md-typeset details.summary{border-color:#00b0ff}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary,.md-typeset .tldr>.admonition-title,.md-typeset .tldr>summary,.md-typeset .summary>.admonition-title,.md-typeset .summary>summary{background-color:rgba(0,176,255,.1);border-color:#00b0ff}.md-typeset .abstract>.admonition-title::before,.md-typeset .abstract>summary::before,.md-typeset .tldr>.admonition-title::before,.md-typeset .tldr>summary::before,.md-typeset .summary>.admonition-title::before,.md-typeset .summary>summary::before{background-color:#00b0ff;mask-image:var(--md-admonition-icon--abstract);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.info,.md-typeset details.info,.md-typeset .admonition.todo,.md-typeset details.todo{border-color:#00b8d4}.md-typeset .info>.admonition-title,.md-typeset .info>summary,.md-typeset .todo>.admonition-title,.md-typeset .todo>summary{background-color:rgba(0,184,212,.1);border-color:#00b8d4}.md-typeset .info>.admonition-title::before,.md-typeset .info>summary::before,.md-typeset .todo>.admonition-title::before,.md-typeset .todo>summary::before{background-color:#00b8d4;mask-image:var(--md-admonition-icon--info);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.tip,.md-typeset details.tip,.md-typeset .admonition.important,.md-typeset details.important,.md-typeset .admonition.hint,.md-typeset details.hint{border-color:#00bfa5}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary,.md-typeset .important>.admonition-title,.md-typeset .important>summary,.md-typeset .hint>.admonition-title,.md-typeset .hint>summary{background-color:rgba(0,191,165,.1);border-color:#00bfa5}.md-typeset .tip>.admonition-title::before,.md-typeset .tip>summary::before,.md-typeset .important>.admonition-title::before,.md-typeset .important>summary::before,.md-typeset .hint>.admonition-title::before,.md-typeset .hint>summary::before{background-color:#00bfa5;mask-image:var(--md-admonition-icon--tip);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.success,.md-typeset details.success,.md-typeset .admonition.done,.md-typeset details.done,.md-typeset .admonition.check,.md-typeset details.check{border-color:#00c853}.md-typeset .success>.admonition-title,.md-typeset .success>summary,.md-typeset .done>.admonition-title,.md-typeset .done>summary,.md-typeset .check>.admonition-title,.md-typeset .check>summary{background-color:rgba(0,200,83,.1);border-color:#00c853}.md-typeset .success>.admonition-title::before,.md-typeset .success>summary::before,.md-typeset .done>.admonition-title::before,.md-typeset .done>summary::before,.md-typeset .check>.admonition-title::before,.md-typeset .check>summary::before{background-color:#00c853;mask-image:var(--md-admonition-icon--success);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.question,.md-typeset details.question,.md-typeset .admonition.faq,.md-typeset details.faq,.md-typeset .admonition.help,.md-typeset details.help{border-color:#64dd17}.md-typeset .question>.admonition-title,.md-typeset .question>summary,.md-typeset .faq>.admonition-title,.md-typeset .faq>summary,.md-typeset .help>.admonition-title,.md-typeset .help>summary{background-color:rgba(100,221,23,.1);border-color:#64dd17}.md-typeset .question>.admonition-title::before,.md-typeset .question>summary::before,.md-typeset .faq>.admonition-title::before,.md-typeset .faq>summary::before,.md-typeset .help>.admonition-title::before,.md-typeset .help>summary::before{background-color:#64dd17;mask-image:var(--md-admonition-icon--question);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.warning,.md-typeset details.warning,.md-typeset .admonition.attention,.md-typeset details.attention,.md-typeset .admonition.caution,.md-typeset details.caution{border-color:#ff9100}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary,.md-typeset .attention>.admonition-title,.md-typeset .attention>summary,.md-typeset .caution>.admonition-title,.md-typeset .caution>summary{background-color:rgba(255,145,0,.1);border-color:#ff9100}.md-typeset .warning>.admonition-title::before,.md-typeset .warning>summary::before,.md-typeset .attention>.admonition-title::before,.md-typeset .attention>summary::before,.md-typeset .caution>.admonition-title::before,.md-typeset .caution>summary::before{background-color:#ff9100;mask-image:var(--md-admonition-icon--warning);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.failure,.md-typeset details.failure,.md-typeset .admonition.missing,.md-typeset details.missing,.md-typeset .admonition.fail,.md-typeset details.fail{border-color:#ff5252}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary,.md-typeset .missing>.admonition-title,.md-typeset .missing>summary,.md-typeset .fail>.admonition-title,.md-typeset .fail>summary{background-color:rgba(255,82,82,.1);border-color:#ff5252}.md-typeset .failure>.admonition-title::before,.md-typeset .failure>summary::before,.md-typeset .missing>.admonition-title::before,.md-typeset .missing>summary::before,.md-typeset .fail>.admonition-title::before,.md-typeset .fail>summary::before{background-color:#ff5252;mask-image:var(--md-admonition-icon--failure);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.danger,.md-typeset details.danger,.md-typeset .admonition.error,.md-typeset details.error{border-color:#ff1744}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary,.md-typeset .error>.admonition-title,.md-typeset .error>summary{background-color:rgba(255,23,68,.1);border-color:#ff1744}.md-typeset .danger>.admonition-title::before,.md-typeset .danger>summary::before,.md-typeset .error>.admonition-title::before,.md-typeset .error>summary::before{background-color:#ff1744;mask-image:var(--md-admonition-icon--danger);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:rgba(245,0,87,.1);border-color:#f50057}.md-typeset .bug>.admonition-title::before,.md-typeset .bug>summary::before{background-color:#f50057;mask-image:var(--md-admonition-icon--bug);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.example,.md-typeset details.example{border-color:#651fff}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:rgba(101,31,255,.1);border-color:#651fff}.md-typeset .example>.admonition-title::before,.md-typeset .example>summary::before{background-color:#651fff;mask-image:var(--md-admonition-icon--example);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.quote,.md-typeset details.quote,.md-typeset .admonition.cite,.md-typeset details.cite{border-color:#9e9e9e}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary,.md-typeset .cite>.admonition-title,.md-typeset .cite>summary{background-color:rgba(158,158,158,.1);border-color:#9e9e9e}.md-typeset .quote>.admonition-title::before,.md-typeset .quote>summary::before,.md-typeset .cite>.admonition-title::before,.md-typeset .cite>summary::before{background-color:#9e9e9e;mask-image:var(--md-admonition-icon--quote);mask-repeat:no-repeat;mask-size:contain}:root{--md-footnotes-icon: svg-load(\"@mdi/svg/svg/keyboard-return.svg\")}.md-typeset [id^=\"fnref:\"]:target{scroll-margin-top:initial;margin-top:-3.4rem;padding-top:3.4rem}.md-typeset [id^=\"fn:\"]:target{scroll-margin-top:initial;margin-top:-3.45rem;padding-top:3.45rem}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}.md-typeset .footnote ol{margin-left:0}.md-typeset .footnote li{transition:color 125ms}.md-typeset .footnote li:target{color:var(--md-default-fg-color)}.md-typeset .footnote li:hover .footnote-backref,.md-typeset .footnote li:target .footnote-backref{transform:translateX(0);opacity:1}.md-typeset .footnote li>:first-child{margin-top:0}.md-typeset .footnote-backref{display:inline-block;color:var(--md-typeset-a-color);font-size:0;vertical-align:text-bottom;transform:translateX(0.25rem);opacity:0;transition:color 250ms,transform 250ms 250ms,opacity 125ms 250ms}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);transform:translateX(0);opacity:1}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-0.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref::before{display:inline-block;width:.8rem;height:.8rem;background-color:currentColor;mask-image:var(--md-footnotes-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .footnote-backref::before svg{transform:scaleX(-1)}.md-typeset .headerlink{display:inline-block;margin-left:.5rem;color:var(--md-default-fg-color--lighter);opacity:0;transition:color 250ms,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem;margin-left:initial}.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink,.md-typeset .headerlink:focus{opacity:1;transition:color 250ms,opacity 125ms}.md-typeset :target>.headerlink,.md-typeset .headerlink:focus,.md-typeset .headerlink:hover{color:var(--md-accent-fg-color)}.md-typeset :target{scroll-margin-top:3.6rem}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{scroll-margin-top:initial}.md-typeset h1:target::before,.md-typeset h2:target::before,.md-typeset h3:target::before{display:block;margin-top:-3.4rem;padding-top:3.4rem;content:\"\"}.md-typeset h4:target{scroll-margin-top:initial}.md-typeset h4:target::before{display:block;margin-top:-3.45rem;padding-top:3.45rem;content:\"\"}.md-typeset h5:target,.md-typeset h6:target{scroll-margin-top:initial}.md-typeset h5:target::before,.md-typeset h6:target::before{display:block;margin-top:-3.6rem;padding-top:3.6rem;content:\"\"}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width: 44.9375em){.md-typeset div.arithmatex{margin:0 -0.8rem}}.md-typeset div.arithmatex>*{width:min-content;margin:1em auto !important;padding:0 .8rem;touch-action:auto}.md-typeset del.critic,.md-typeset ins.critic,.md-typeset .critic.comment{box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment::before{content:\"/* \"}.md-typeset .critic.comment::after{content:\" */\"}.md-typeset .critic.block{display:block;margin:1em 0;padding-right:.8rem;padding-left:.8rem;overflow:auto;box-shadow:none}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon: svg-load(\"@mdi/svg/svg/chevron-right.svg\")}.md-typeset details{display:block;padding-top:0;overflow:visible}.md-typeset details[open]>summary::after{transform:rotate(90deg)}.md-typeset details:not([open]){padding-bottom:0;box-shadow:none}.md-typeset details:not([open])>summary{border-radius:.1rem}.md-typeset details::after{display:table;content:\"\"}.md-typeset summary{display:block;min-height:1rem;padding:.4rem 1.8rem .4rem 2rem;border-top-left-radius:.1rem;border-top-right-radius:.1rem;cursor:pointer}[dir=rtl] .md-typeset summary{padding:.4rem 2.2rem .4rem 1.8rem}.md-typeset summary:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset summary::after{position:absolute;top:.4rem;right:.4rem;width:1rem;height:1rem;background-color:currentColor;mask-image:var(--md-details-icon);mask-repeat:no-repeat;mask-size:contain;transform:rotate(0deg);transition:transform 250ms;content:\"\"}[dir=rtl] .md-typeset summary::after{right:initial;left:.4rem;transform:rotate(180deg)}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .twemoji,.md-typeset .gemoji{display:inline-block;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .twemoji svg,.md-typeset .gemoji svg{width:1.125em;max-height:100%;fill:currentColor}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .sb,.highlight .sc,.highlight .s2,.highlight .si,.highlight .s1,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .m,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .no,.highlight .nb,.highlight .bp{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .cm,.highlight .c1,.highlight .ch,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gr,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gs,.highlight .gu,.highlight .gt{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{margin:0 -0.125em;padding:0 .125em;border-radius:.1rem}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em;background-color:var(--md-code-hl-color)}.highlight [data-linenos]::before{position:sticky;left:-1.1764705882em;float:left;margin-right:1.1764705882em;margin-left:-1.1764705882em;padding-left:1.1764705882em;color:var(--md-default-fg-color--light);background-color:var(--md-code-bg-color);box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset;content:attr(data-linenos);user-select:none}.highlighttable{display:flow-root;overflow:hidden}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable .linenos{padding:.7720588235em 1.1764705882em;padding-right:0;font-size:.85em;background-color:var(--md-code-bg-color);user-select:none}.highlighttable .linenodiv{padding-right:.5882352941em;box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;overflow:hidden}.md-typeset .highlighttable{margin:1em 0;direction:ltr;border-radius:.1rem}.md-typeset .highlighttable code{border-radius:0}@media screen and (max-width: 44.9375em){.md-typeset>.highlight{margin:1em -0.8rem}.md-typeset>.highlight .hll{margin:0 -0.8rem;padding:0 .8rem}.md-typeset>.highlight code{border-radius:0}.md-typeset>.highlighttable{margin:1em -0.8rem;border-radius:0}.md-typeset>.highlighttable .hll{margin:0 -0.8rem;padding:0 .8rem}}.md-typeset .keys kbd::before,.md-typeset .keys kbd::after{position:relative;margin:0;color:inherit;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial}.md-typeset .keys span{padding:0 .2em;color:var(--md-default-fg-color--light)}.md-typeset .keys .key-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-left-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-right-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-left-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-right-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-left-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-right-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-left-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-right-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-left-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-right-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-left-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-right-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-left-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-right-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-left-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-right-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-arrow-down::before{padding-right:.4em;content:\"↓\"}.md-typeset .keys .key-arrow-left::before{padding-right:.4em;content:\"←\"}.md-typeset .keys .key-arrow-right::before{padding-right:.4em;content:\"→\"}.md-typeset .keys .key-arrow-up::before{padding-right:.4em;content:\"↑\"}.md-typeset .keys .key-backspace::before{padding-right:.4em;content:\"⌫\"}.md-typeset .keys .key-backtab::before{padding-right:.4em;content:\"⇤\"}.md-typeset .keys .key-caps-lock::before{padding-right:.4em;content:\"⇪\"}.md-typeset .keys .key-clear::before{padding-right:.4em;content:\"⌧\"}.md-typeset .keys .key-context-menu::before{padding-right:.4em;content:\"☰\"}.md-typeset .keys .key-delete::before{padding-right:.4em;content:\"⌦\"}.md-typeset .keys .key-eject::before{padding-right:.4em;content:\"⏏\"}.md-typeset .keys .key-end::before{padding-right:.4em;content:\"⤓\"}.md-typeset .keys .key-escape::before{padding-right:.4em;content:\"⎋\"}.md-typeset .keys .key-home::before{padding-right:.4em;content:\"⤒\"}.md-typeset .keys .key-insert::before{padding-right:.4em;content:\"⎀\"}.md-typeset .keys .key-page-down::before{padding-right:.4em;content:\"⇟\"}.md-typeset .keys .key-page-up::before{padding-right:.4em;content:\"⇞\"}.md-typeset .keys .key-print-screen::before{padding-right:.4em;content:\"⎙\"}.md-typeset .keys .key-tab::after{padding-left:.4em;content:\"⇥\"}.md-typeset .keys .key-num-enter::after{padding-left:.4em;content:\"⌤\"}.md-typeset .keys .key-enter::after{padding-left:.4em;content:\"⏎\"}.md-typeset .tabbed-content{display:none;order:99;width:100%;box-shadow:0 -0.05rem var(--md-default-fg-color--lightest)}@media print{.md-typeset .tabbed-content{display:block;order:initial}}.md-typeset .tabbed-content>pre:only-child,.md-typeset .tabbed-content>.highlight:only-child pre,.md-typeset .tabbed-content>.highlighttable:only-child{margin:0}.md-typeset .tabbed-content>pre:only-child>code,.md-typeset .tabbed-content>.highlight:only-child pre>code,.md-typeset .tabbed-content>.highlighttable:only-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-content>.tabbed-set{margin:0}.md-typeset .tabbed-set{position:relative;display:flex;flex-wrap:wrap;margin:1em 0;border-radius:.1rem}.md-typeset .tabbed-set>input{position:absolute;width:0;height:0;opacity:0}.md-typeset .tabbed-set>input:checked+label{color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:checked+label+.tabbed-content{display:block}.md-typeset .tabbed-set>input:focus+label{outline-style:auto}.md-typeset .tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.md-typeset .tabbed-set>label{z-index:1;width:auto;padding:.9375em 1.25em .78125em;color:var(--md-default-fg-color--light);font-weight:700;font-size:.64rem;border-bottom:.1rem solid transparent;cursor:pointer;transition:color 250ms}.md-typeset .tabbed-set>label:hover{color:var(--md-accent-fg-color)}:root{--md-tasklist-icon: svg-load( \"@primer/octicons/build/svg/check-circle-fill-24.svg\" );--md-tasklist-icon--checked: svg-load( \"@primer/octicons/build/svg/check-circle-fill-24.svg\" )}.md-typeset .task-list-item{position:relative;list-style-type:none}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em;left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em;left:initial}.md-typeset .task-list-control [type=checkbox]{z-index:-1;opacity:0}.md-typeset .task-list-indicator::before{position:absolute;top:.15em;left:-1.5em;width:1.25em;height:1.25em;background-color:var(--md-default-fg-color--lightest);mask-image:var(--md-tasklist-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .task-list-indicator::before{right:-1.5em;left:initial}.md-typeset [type=checkbox]:checked+.task-list-indicator::before{background-color:#00e676;mask-image:var(--md-tasklist-icon--checked)}","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Enforce correct box model and prevent adjustments of font size after\n// orientation changes in IE and iOS\nhtml {\n box-sizing: border-box;\n text-size-adjust: none;\n}\n\n// All elements shall inherit the document default\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n// Remove margin in all browsers\nbody {\n margin: 0;\n}\n\n// Reset tap outlines on iOS and Android\na,\nbutton,\nlabel,\ninput {\n -webkit-tap-highlight-color: transparent;\n}\n\n// Reset link styles\na {\n color: inherit;\n text-decoration: none;\n}\n\n// Normalize horizontal separator styles\nhr {\n display: block;\n box-sizing: content-box;\n height: px2rem(1px);\n padding: 0;\n overflow: visible;\n border: 0;\n}\n\n// Normalize font-size in all browsers\nsmall {\n font-size: 80%;\n}\n\n// Prevent subscript and superscript from affecting line-height\nsub,\nsup {\n line-height: 1em;\n}\n\n// Remove border on image\nimg {\n border-style: none;\n}\n\n// Reset table styles\ntable {\n border-collapse: separate;\n border-spacing: 0;\n}\n\n// Reset table cell styles\ntd,\nth {\n font-weight: 400;\n vertical-align: top;\n}\n\n// Reset button styles\nbutton {\n margin: 0;\n padding: 0;\n font-size: inherit;\n background: transparent;\n border: 0;\n}\n\n// Reset input styles\ninput {\n border: 0;\n outline: none;\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Color definitions\n:root {\n\n // Default color shades\n --md-default-fg-color: hsla(0, 0%, 0%, 0.87);\n --md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);\n --md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);\n --md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);\n --md-default-bg-color: hsla(0, 0%, 100%, 1);\n --md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);\n --md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);\n\n // Primary color shades\n --md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n --md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1);\n --md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1);\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Accent color shades\n --md-accent-fg-color: hsla(#{hex2hsl($clr-indigo-a200)}, 1);\n --md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-indigo-a200)}, 0.1);\n --md-accent-bg-color: hsla(0, 0%, 100%, 1);\n --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Light theme (default)\n > * {\n\n // Code color shades\n --md-code-fg-color: hsla(200, 18%, 26%, 1);\n --md-code-bg-color: hsla(0, 0%, 96%, 1);\n\n // Code highlighting color shades\n --md-code-hl-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5);\n --md-code-hl-number-color: hsla(0, 67%, 50%, 1);\n --md-code-hl-special-color: hsla(340, 83%, 47%, 1);\n --md-code-hl-function-color: hsla(291, 45%, 50%, 1);\n --md-code-hl-constant-color: hsla(250, 63%, 60%, 1);\n --md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);\n --md-code-hl-string-color: hsla(150, 63%, 30%, 1);\n --md-code-hl-name-color: var(--md-code-fg-color);\n --md-code-hl-operator-color: var(--md-default-fg-color--light);\n --md-code-hl-punctuation-color: var(--md-default-fg-color--light);\n --md-code-hl-comment-color: var(--md-default-fg-color--light);\n --md-code-hl-generic-color: var(--md-default-fg-color--light);\n --md-code-hl-variable-color: var(--md-default-fg-color--light);\n\n // Typeset color shades\n --md-typeset-color: var(--md-default-fg-color);\n --md-typeset-a-color: var(--md-primary-fg-color);\n\n // Typeset `mark` color shades\n --md-typeset-mark-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5);\n\n // Typeset `del` and `ins` color shades\n --md-typeset-del-color: hsla(6, 90%, 60%, 0.15);\n --md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);\n\n // Typeset `kbd` color shades\n --md-typeset-kbd-color: hsla(0, 0%, 98%, 1);\n --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);\n --md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);\n\n // Admonition color shades\n --md-admonition-fg-color: var(--md-default-fg-color);\n --md-admonition-bg-color: var(--md-default-bg-color);\n\n // Footer color shades\n --md-footer-fg-color: hsla(0, 0%, 100%, 1);\n --md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);\n --md-footer-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32);\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon\n.md-icon {\n\n // SVG defaults\n svg {\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n fill: currentColor;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: font definitions\n// ----------------------------------------------------------------------------\n\n// Enable font-smoothing in Webkit and FF\nbody {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Define default fonts\nbody,\ninput {\n color: var(--md-typeset-color);\n font-feature-settings: \"kern\", \"liga\";\n font-family: -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;\n}\n\n// Define proportionally spaced fonts\ncode,\npre,\nkbd {\n color: var(--md-typeset-color);\n font-feature-settings: \"kern\";\n font-family: SFMono-Regular, Consolas, Menlo, monospace;\n}\n\n// ----------------------------------------------------------------------------\n// Rules: typesetted content\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-typeset-table--ascending: svg-load(\"@mdi/svg/svg/arrow-down.svg\");\n --md-typeset-table--descending: svg-load(\"@mdi/svg/svg/arrow-up.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Content that is typeset - if possible, all margins, paddings and font sizes\n// should be set in ems, so nested blocks (e.g. admonitions) render correctly.\n.md-typeset {\n font-size: px2rem(16px);\n line-height: 1.6;\n color-adjust: exact;\n\n // [print]: We'll use a smaller `font-size` for printing, so code examples\n // don't break too early, and `16px` looks too big anyway.\n @media print {\n font-size: px2rem(13.6px);\n }\n\n // Default spacing\n p,\n ul,\n ol,\n dl,\n blockquote {\n margin: 1em 0;\n }\n\n // Headline on level 1\n h1 {\n margin: 0 0 px2em(40px, 32px);\n color: var(--md-default-fg-color--light);\n font-weight: 300;\n font-size: px2em(32px);\n line-height: 1.3;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 2\n h2 {\n margin: px2em(40px, 25px) 0 px2em(16px, 25px);\n font-weight: 300;\n font-size: px2em(25px);\n line-height: 1.4;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 3\n h3 {\n margin: px2em(32px, 20px) 0 px2em(16px, 20px);\n font-weight: 400;\n font-size: px2em(20px);\n line-height: 1.5;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 3 following level 2\n h2 + h3 {\n margin-top: px2em(16px, 20px);\n }\n\n // Headline on level 4\n h4 {\n margin: px2em(16px) 0;\n font-weight: 700;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 5-6\n h5,\n h6 {\n margin: px2em(16px, 12.8px) 0;\n color: var(--md-default-fg-color--light);\n font-weight: 700;\n font-size: px2em(12.8px);\n letter-spacing: -0.01em;\n }\n\n // Headline on level 5\n h5 {\n text-transform: uppercase;\n }\n\n // Horizontal separator\n hr {\n margin: 1.5em 0;\n border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest);\n }\n\n // Text link\n a {\n color: var(--md-typeset-a-color);\n word-break: break-word;\n\n // Also enable color transition on pseudo elements\n &,\n &::before {\n transition: color 125ms;\n }\n\n // Text link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n\n // Code blocks\n code,\n pre,\n kbd {\n color: var(--md-code-fg-color);\n direction: ltr;\n\n // [print]: Wrap text and hide scollbars\n @media print {\n white-space: pre-wrap;\n }\n }\n\n // Inline code blocks\n code {\n padding: 0 px2em(4px, 13.6px);\n font-size: px2em(13.6px);\n word-break: break-word;\n background-color: var(--md-code-bg-color);\n border-radius: px2rem(2px);\n box-decoration-break: clone;\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n // Code block in headline\n h1 code,\n h2 code,\n h3 code,\n h4 code,\n h5 code,\n h6 code {\n margin: initial;\n padding: initial;\n background-color: transparent;\n box-shadow: none;\n }\n\n // Ensure link color in code blocks\n a > code {\n color: currentColor;\n }\n\n // Unformatted content\n pre {\n position: relative;\n margin: 1em 0;\n line-height: 1.4;\n\n // Code block\n > code {\n display: block;\n margin: 0;\n padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px);\n overflow: auto;\n word-break: normal;\n box-shadow: none;\n box-decoration-break: slice;\n touch-action: auto;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Code block on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n }\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n\n // Unformatted text\n > pre {\n margin: 1em px2rem(-16px);\n\n // Code block\n code {\n border-radius: 0;\n }\n }\n }\n\n // Keyboard key\n kbd {\n display: inline-block;\n padding: 0 px2em(8px, 12px);\n color: var(--md-default-fg-color);\n font-size: px2em(12px);\n vertical-align: text-top;\n word-break: break-word;\n background-color: var(--md-typeset-kbd-color);\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(2px) 0 px2rem(1px) var(--md-typeset-kbd-border-color),\n 0 px2rem(2px) 0 var(--md-typeset-kbd-border-color),\n 0 px2rem(-2px) px2rem(4px) var(--md-typeset-kbd-accent-color) inset;\n }\n\n // Text highlighting marker\n mark {\n color: inherit;\n word-break: break-word;\n background-color: var(--md-typeset-mark-color);\n box-decoration-break: clone;\n }\n\n // Abbreviation\n abbr {\n text-decoration: none;\n border-bottom: px2rem(1px) dotted var(--md-default-fg-color--light);\n cursor: help;\n\n // Show tooltip for touch devices\n @media (hover: none) {\n position: relative;\n\n // Tooltip\n &[title]:focus::after,\n &[title]:hover::after {\n @include z-depth(2);\n\n position: absolute;\n left: 0;\n display: inline-block;\n width: auto;\n min-width: max-content;\n max-width: 80%;\n margin-top: 2em;\n padding: px2rem(4px) px2rem(6px);\n color: var(--md-default-bg-color);\n font-size: px2rem(14px);\n background-color: var(--md-default-fg-color);\n border-radius: px2rem(2px);\n content: attr(title);\n }\n }\n\n }\n\n // Small text\n small {\n opacity: 0.75;\n }\n\n // Superscript and subscript\n sup,\n sub {\n margin-left: px2em(1px, 12.8px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(1px, 12.8px);\n margin-left: initial;\n }\n }\n\n // Blockquotes, possibly nested\n blockquote {\n padding-left: px2rem(12px);\n color: var(--md-default-fg-color--light);\n border-left: px2rem(4px) solid var(--md-default-fg-color--lighter);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(12px);\n padding-left: initial;\n border-right: px2rem(4px) solid var(--md-default-fg-color--lighter);\n border-left: initial;\n }\n }\n\n // Unordered list\n ul {\n list-style-type: disc;\n }\n\n // Unordered and ordered list\n ul,\n ol {\n margin-left: px2em(10px);\n padding: 0;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(10px);\n margin-left: initial;\n }\n\n // Nested ordered list\n ol {\n list-style-type: lower-alpha;\n\n // Triply nested ordered list\n ol {\n list-style-type: lower-roman;\n }\n }\n\n // List element\n li {\n margin-bottom: 0.5em;\n margin-left: px2em(20px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(20px);\n margin-left: initial;\n }\n\n // Adjust spacing\n p,\n blockquote {\n margin: 0.5em 0;\n }\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n\n // Nested list\n ul,\n ol {\n margin: 0.5em 0 0.5em px2em(10px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(10px);\n margin-left: initial;\n }\n }\n }\n }\n\n // Definition list\n dd {\n margin: 1em 0 1.5em px2em(30px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(30px);\n margin-left: initial;\n }\n }\n\n // Image or icon\n img,\n svg {\n max-width: 100%;\n height: auto;\n\n // Adjust spacing when left-aligned\n &[align=\"left\"] {\n margin: 1em;\n margin-left: 0;\n }\n\n // Adjust spacing when right-aligned\n &[align=\"right\"] {\n margin: 1em;\n margin-right: 0;\n }\n\n // Adjust spacing when sole children\n &[align]:only-child {\n margin-top: 0;\n }\n }\n\n // Figure\n figure {\n width: fit-content;\n max-width: 100%;\n margin: 0 auto;\n text-align: center;\n\n // Figure images\n img {\n display: block;\n }\n }\n\n // Figure caption\n figcaption {\n max-width: px2rem(480px);\n margin: 1em auto 2em;\n font-style: italic;\n }\n\n // Limit width to container\n iframe {\n max-width: 100%;\n }\n\n // Data table\n table:not([class]) {\n display: inline-block;\n max-width: 100%;\n overflow: auto;\n font-size: px2rem(12.8px);\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(4px) px2rem(10px) hsla(0, 0%, 0%, 0.05),\n 0 0 px2rem(1px) hsla(0, 0%, 0%, 0.1);\n touch-action: auto;\n\n // [print]: Reset display mode so table header wraps when printing\n @media print {\n display: table;\n }\n\n // Due to margin collapse because of the necessary inline-block hack, we\n // cannot increase the bottom margin on the table, so we just increase the\n // top margin on the following element\n & + * {\n margin-top: 1.5em;\n }\n\n // Elements in table heading and cell\n th > *,\n td > * {\n\n // Adjust spacing on first child\n &:first-child {\n margin-top: 0;\n }\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Table heading and cell\n th:not([align]),\n td:not([align]) {\n text-align: left;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n text-align: right;\n }\n }\n\n // Table heading\n th {\n min-width: px2rem(100px);\n padding: px2em(12px, 12.8px) px2em(16px, 12.8px);\n color: var(--md-default-bg-color);\n vertical-align: top;\n background-color: var(--md-default-fg-color--light);\n\n // Links in table headings\n a {\n color: inherit;\n }\n }\n\n // Table cell\n td {\n padding: px2em(12px, 12.8px) px2em(16px, 12.8px);\n vertical-align: top;\n border-top: px2rem(1px) solid var(--md-default-fg-color--lightest);\n }\n\n // Table row\n tr {\n transition: background-color 125ms;\n\n // Table row on hover\n &:hover {\n background-color: rgba(0, 0, 0, 0.035);\n box-shadow: 0 px2rem(1px) 0 var(--md-default-bg-color) inset;\n }\n\n // Hide border on first table row\n &:first-child td {\n border-top: 0;\n }\n }\n\n // Text link in table\n a {\n word-break: normal;\n }\n }\n\n // Sortable table\n table th[role=\"columnheader\"] {\n cursor: pointer;\n\n // Sort icon\n &::after {\n display: inline-block;\n width: 1.2em;\n height: 1.2em;\n margin-left: 0.5em;\n vertical-align: sub;\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Sort ascending\n &[aria-sort=\"ascending\"]::after {\n background-color: currentColor;\n mask-image: var(--md-typeset-table--ascending);\n }\n\n // Sort descending\n &[aria-sort=\"descending\"]::after {\n background-color: currentColor;\n mask-image: var(--md-typeset-table--descending);\n }\n }\n\n // Data table scroll wrapper\n &__scrollwrap {\n margin: 1em px2rem(-16px);\n overflow-x: auto;\n touch-action: auto;\n }\n\n // Data table wrapper\n &__table {\n display: inline-block;\n margin-bottom: 0.5em;\n padding: 0 px2rem(16px);\n\n // [print]: Reset display mode so table header wraps when printing\n @media print {\n display: block;\n }\n\n // Data table\n html & table {\n display: table;\n width: 100%;\n margin: 0;\n overflow: hidden;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n///\n/// Device-specific breakpoints\n///\n/// @example\n/// $break-devices: (\n/// mobile: (\n/// portrait: 220px 479px,\n/// landscape: 480px 719px\n/// ),\n/// tablet: (\n/// portrait: 720px 959px,\n/// landscape: 960px 1219px\n/// ),\n/// screen: (\n/// small: 1220px 1599px,\n/// medium: 1600px 1999px,\n/// large: 2000px\n/// )\n/// );\n///\n$break-devices: () !default;\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n///\n/// Choose minimum and maximum device widths\n///\n@function break-select-min-max($devices) {\n $min: 1000000;\n $max: 0;\n @each $key, $value in $devices {\n @while type-of($value) == map {\n $value: break-select-min-max($value);\n }\n @if type-of($value) == list {\n @each $number in $value {\n @if type-of($number) == number {\n $min: min($number, $min);\n @if $max != null {\n $max: max($number, $max);\n }\n } @else {\n @error \"Invalid number: #{$number}\";\n }\n }\n } @else if type-of($value) == number {\n $min: min($value, $min);\n $max: null;\n } @else {\n @error \"Invalid value: #{$value}\";\n }\n }\n @return $min, $max;\n}\n\n///\n/// Select minimum and maximum widths for a device breakpoint\n///\n@function break-select-device($device) {\n $current: $break-devices;\n @for $n from 1 through length($device) {\n @if type-of($current) == map {\n $current: map-get($current, nth($device, $n));\n } @else {\n @error \"Invalid device map: #{$devices}\";\n }\n }\n @if type-of($current) == list or type-of($current) == number {\n $current: (default: $current);\n }\n @return break-select-min-max($current);\n}\n\n// ----------------------------------------------------------------------------\n// Mixins\n// ----------------------------------------------------------------------------\n\n///\n/// A minimum-maximum media query breakpoint\n///\n@mixin break-at($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (min-width: $breakpoint) {\n @content;\n }\n } @else if type-of($breakpoint) == list {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @if type-of($min) == number and type-of($max) == number {\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// An orientation media query breakpoint\n///\n@mixin break-at-orientation($breakpoint) {\n @if type-of($breakpoint) == string {\n @media screen and (orientation: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A maximum-aspect-ratio media query breakpoint\n///\n@mixin break-at-ratio($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (max-aspect-ratio: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A minimum-maximum media query device breakpoint\n///\n@mixin break-at-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n @if nth($breakpoint, 2) != null {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A minimum media query device breakpoint\n///\n@mixin break-from-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $min: nth($breakpoint, 1);\n @media screen and (min-width: $min) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A maximum media query device breakpoint\n///\n@mixin break-to-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $max: nth($breakpoint, 2);\n @media screen and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n","//\n// Name: Material Shadows\n// Description: Mixins for Material Design Shadows.\n// Version: 3.0.1\n//\n// Author: Denis Malinochkin\n// Git: https://github.com/mrmlnc/material-shadows\n//\n// twitter: @mrmlnc\n//\n// ------------------------------------\n\n\n// Mixins\n// ------------------------------------\n\n@mixin z-depth-transition() {\n transition: box-shadow .28s cubic-bezier(.4, 0, .2, 1);\n}\n\n@mixin z-depth-focus() {\n box-shadow: 0 0 8px rgba(0, 0, 0, .18), 0 8px 16px rgba(0, 0, 0, .36);\n}\n\n@mixin z-depth-2dp() {\n box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14),\n 0 1px 5px 0 rgba(0, 0, 0, .12),\n 0 3px 1px -2px rgba(0, 0, 0, .2);\n}\n\n@mixin z-depth-3dp() {\n box-shadow: 0 3px 4px 0 rgba(0, 0, 0, .14),\n 0 1px 8px 0 rgba(0, 0, 0, .12),\n 0 3px 3px -2px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-4dp() {\n box-shadow: 0 4px 5px 0 rgba(0, 0, 0, .14),\n 0 1px 10px 0 rgba(0, 0, 0, .12),\n 0 2px 4px -1px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-6dp() {\n box-shadow: 0 6px 10px 0 rgba(0, 0, 0, .14),\n 0 1px 18px 0 rgba(0, 0, 0, .12),\n 0 3px 5px -1px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-8dp() {\n box-shadow: 0 8px 10px 1px rgba(0, 0, 0, .14),\n 0 3px 14px 2px rgba(0, 0, 0, .12),\n 0 5px 5px -3px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-16dp() {\n box-shadow: 0 16px 24px 2px rgba(0, 0, 0, .14),\n 0 6px 30px 5px rgba(0, 0, 0, .12),\n 0 8px 10px -5px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-24dp() {\n box-shadow: 0 9px 46px 8px rgba(0, 0, 0, .14),\n 0 24px 38px 3px rgba(0, 0, 0, .12),\n 0 11px 15px -7px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth($dp: 2) {\n @if $dp == 2 {\n @include z-depth-2dp();\n } @else if $dp == 3 {\n @include z-depth-3dp();\n } @else if $dp == 4 {\n @include z-depth-4dp();\n } @else if $dp == 6 {\n @include z-depth-6dp();\n } @else if $dp == 8 {\n @include z-depth-8dp();\n } @else if $dp == 16 {\n @include z-depth-16dp();\n } @else if $dp == 24 {\n @include z-depth-24dp();\n }\n}\n\n\n// Class generator\n// ------------------------------------\n\n@mixin z-depth-classes($transition: false, $focus: false) {\n @if $transition == true {\n &-transition {\n @include z-depth-transition();\n }\n }\n\n @if $focus == true {\n &-focus {\n @include z-depth-focus();\n }\n }\n\n // The available values for the shadow depth\n @each $depth in 2, 3, 4, 6, 8, 16, 24 {\n &-#{$depth}dp {\n @include z-depth($depth);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: base grid and containers\n// ----------------------------------------------------------------------------\n\n// Stretch container to viewport and set base `font-size`\nhtml {\n height: 100%;\n overflow-x: hidden;\n // Hack: normally, we would set the base `font-size` to `62.5%`, so we can\n // base all calculations on `10px`, but Chromium and Chrome define a minimal\n // `font-size` of `12px` if the system language is set to Chinese. For this\n // reason we just double the `font-size` and set it to `20px`.\n //\n // See https://github.com/squidfunk/mkdocs-material/issues/911\n font-size: 125%;\n\n // [screen medium +]: Set base `font-size` to `11px`\n @include break-from-device(screen medium) {\n font-size: 137.50%;\n }\n\n // [screen large +]: Set base `font-size` to `12px`\n @include break-from-device(screen large) {\n font-size: 150%;\n }\n}\n\n// Stretch body to container - flexbox is used, so the footer will always be\n// aligned to the bottom of the viewport\nbody {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n // Hack: reset `font-size` to `10px`, so the spacing for all inline elements\n // is correct again. Otherwise the spacing would be based on `20px`.\n font-size: px2rem(10px);\n background-color: var(--md-default-bg-color);\n\n // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m)\n @media print {\n display: block;\n }\n\n // Body in locked state\n &[data-md-state=\"lock\"] {\n\n // [tablet portrait -]: Omit scroll bubbling\n @include break-to-device(tablet portrait) {\n position: fixed;\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Grid container - this class is applied to wrapper elements within the\n// header, content area and footer, and makes sure that their width is limited\n// to `1220px`, and they are rendered centered if the screen is larger.\n.md-grid {\n max-width: px2rem(1220px);\n margin-right: auto;\n margin-left: auto;\n}\n\n// Main container\n.md-container {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n\n // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m)\n @media print {\n display: block;\n }\n}\n\n// Main area - stretch to remaining space of container\n.md-main {\n flex-grow: 1;\n\n // Main area wrapper\n &__inner {\n display: flex;\n height: 100%;\n margin-top: px2rem(24px + 6px);\n }\n}\n\n// Add ellipsis in case of overflowing text\n.md-ellipsis {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n// ----------------------------------------------------------------------------\n// Rules: navigational elements\n// ----------------------------------------------------------------------------\n\n// Toggle - this class is applied to the checkbox elements, which are used to\n// implement the CSS-only drawer and navigation, as well as the search\n.md-toggle {\n display: none;\n}\n\n// Skip link\n.md-skip {\n position: fixed;\n // Hack: if we don't set the negative `z-index`, the skip link will force the\n // creation of new layers when code blocks are near the header on scrolling\n z-index: -1;\n margin: px2rem(10px);\n padding: px2rem(6px) px2rem(10px);\n color: var(--md-default-bg-color);\n font-size: px2rem(12.8px);\n background-color: var(--md-default-fg-color);\n border-radius: px2rem(2px);\n transform: translateY(px2rem(8px));\n opacity: 0;\n\n // Show skip link on focus\n &:focus {\n z-index: 10;\n transform: translateY(0);\n opacity: 1;\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 175ms 75ms;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: print styles\n// ----------------------------------------------------------------------------\n\n// Add margins to page\n@page {\n margin: 25mm;\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Announcement bar\n.md-announce {\n overflow: auto;\n background-color: var(--md-footer-bg-color);\n\n // [print]: Hide announcement bar\n @media print {\n display: none;\n }\n\n // Announcement wrapper\n &__inner {\n margin: px2rem(12px) auto;\n padding: 0 px2rem(16px);\n color: var(--md-footer-fg-color);\n font-size: px2rem(14px);\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Button\n .md-button {\n display: inline-block;\n padding: px2em(10px) px2em(32px);\n color: var(--md-primary-fg-color);\n font-weight: 700;\n border: px2rem(2px) solid currentColor;\n border-radius: px2rem(2px);\n transition:\n color 125ms,\n background-color 125ms,\n border-color 125ms;\n\n // Primary button\n &--primary {\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n border-color: var(--md-primary-fg-color);\n }\n\n // Button on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-bg-color);\n background-color: var(--md-accent-fg-color);\n border-color: var(--md-accent-fg-color);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-clipboard-icon: svg-load(\"@mdi/svg/svg/content-copy.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Button to copy to clipboard\n.md-clipboard {\n position: absolute;\n top: px2em(8px);\n right: px2em(8px);\n z-index: 1;\n width: px2em(24px);\n height: px2em(24px);\n color: var(--md-default-fg-color--lightest);\n border-radius: px2rem(2px);\n cursor: pointer;\n transition: color 250ms;\n\n // [print]: Hide button\n @media print {\n display: none;\n }\n\n // Darken color on code block hover\n :hover > & {\n color: var(--md-default-fg-color--light);\n }\n\n // Button on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Button icon - the width and height are defined in `em`, so the size is\n // automatically adjusted for nested code blocks (e.g. in admonitions)\n &::after {\n display: block;\n width: px2em(18px);\n height: px2em(18px);\n margin: 0 auto;\n background-color: currentColor;\n mask-image: var(--md-clipboard-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Content area\n.md-content {\n flex-grow: 1;\n // Hack: we must use `overflow: hidden`, so the content area is capped by\n // the dimensions of its parent. Otherwise, long code blocks might lead to\n // a wider content area which will break everything. This, however, induces\n // margin collapse, which will break scroll margins. Adding a large enough\n // scroll padding seems to do the trick, at least in Chrome and Firefox.\n overflow: hidden;\n scroll-padding-top: px2rem(1024px);\n\n // Content wrapper\n &__inner {\n margin: 0 px2rem(16px) px2rem(24px);\n padding-top: px2rem(12px);\n\n // [screen +]: Adjust spacing between content area and sidebars\n @include break-from-device(screen) {\n\n // Sidebar with navigation is visible\n .md-sidebar--primary:not([hidden]) ~ .md-content > & {\n margin-left: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(24px);\n margin-left: px2rem(16px);\n }\n }\n\n // Sidebar with table of contents is visible\n .md-sidebar--secondary:not([hidden]) ~ .md-content > & {\n margin-right: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(16px);\n margin-left: px2rem(24px);\n }\n }\n }\n\n // Hack: add pseudo element for spacing, as the overflow of the content\n // container may not be hidden due to an imminent offset error on targets\n &::before {\n display: block;\n height: px2rem(8px);\n content: \"\";\n }\n\n // Adjust spacing on last child\n > :last-child {\n margin-bottom: 0;\n }\n }\n\n // Button inside of the content area - these buttons are meant for actions on\n // a document-level, i.e. linking to related source code files, printing etc.\n &__button {\n float: right;\n margin: px2rem(8px) 0;\n margin-left: px2rem(8px);\n padding: 0;\n\n // [print]: Hide buttons\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n margin-right: px2rem(8px);\n margin-left: initial;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n\n // Adjust default link color for icons\n .md-typeset & {\n color: var(--md-default-fg-color--lighter);\n }\n\n // Align with body copy located next to icon\n svg {\n display: inline;\n vertical-align: top;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Dialog\n.md-dialog {\n @include z-depth(2);\n\n position: fixed;\n right: px2rem(16px);\n bottom: px2rem(16px);\n left: initial;\n z-index: 2;\n display: block;\n min-width: px2rem(222px);\n padding: px2rem(8px) px2rem(12px);\n color: var(--md-default-bg-color);\n font-size: px2rem(14px);\n background-color: var(--md-default-fg-color);\n border: none;\n border-radius: px2rem(2px);\n transform: translateY(100%);\n opacity: 0;\n transition:\n transform 0ms 400ms,\n opacity 400ms;\n\n // [print]: Hide dialog\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(16px);\n }\n\n // Dialog in open state\n &[data-md-state=\"open\"] {\n transform: translateY(0);\n opacity: 1;\n transition:\n transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),\n opacity 400ms;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Header - by default, the header will be sticky and stay always on top of the\n// viewport. If this behavior is not desired, just set `position: static`.\n.md-header {\n position: sticky;\n top: 0;\n right: 0;\n left: 0;\n z-index: 2;\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n // Hack: reduce jitter by adding a transparent box shadow of the same size\n // so the size of the layer doesn't change during animation\n box-shadow:\n 0 0 px2rem(4px) rgba(0, 0, 0, 0),\n 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0);\n transition:\n color 250ms,\n background-color 250ms;\n\n // [print]: Hide header\n @media print {\n display: none;\n }\n\n // Header in shadow state, i.e. shadow is visible\n &[data-md-state=\"shadow\"] {\n box-shadow:\n 0 0 px2rem(4px) rgba(0, 0, 0, 0.1),\n 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0.2);\n transition:\n transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),\n color 250ms,\n background-color 250ms,\n box-shadow 250ms;\n }\n\n // Header in hidden state, i.e. moved out of sight\n &[data-md-state=\"hidden\"] {\n transform: translateY(-100%);\n transition:\n transform 250ms cubic-bezier(0.8, 0, 0.6, 1),\n color 250ms,\n background-color 250ms,\n box-shadow 250ms;\n }\n}\n\n// Header navigation - if the header exceeds the default height of `48px`, i.e.\n// by adding a bigger logo, the items are agned at the center\n.md-header-nav {\n display: flex;\n align-items: center;\n padding: 0 px2rem(4px);\n\n // Header navigation button\n &__button {\n position: relative;\n z-index: 1;\n display: inline-block;\n margin: px2rem(4px);\n padding: px2rem(8px);\n color: currentColor;\n vertical-align: middle;\n cursor: pointer;\n transition: opacity 250ms;\n\n // Button on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n }\n\n // Button with logo, pointing to `config.site_url`\n &.md-logo {\n margin: px2rem(4px);\n padding: px2rem(8px);\n\n // [tablet -]: Hide button\n @include break-to-device(tablet) {\n display: none;\n }\n\n // Image or icon\n img,\n svg {\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n fill: currentColor;\n }\n }\n\n // Button for search\n &[for=\"__search\"] {\n\n // [tablet landscape +]: Hide button\n @include break-from-device(tablet landscape) {\n display: none;\n }\n\n // [no-js]: Hide button\n .no-js & {\n display: none\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n\n // Button for drawer\n &[for=\"__drawer\"] {\n\n // [screen +]: Hide button\n @include break-from-device(screen) {\n display: none;\n }\n }\n }\n\n // Header navigation topic\n &__topic {\n position: absolute;\n display: flex;\n max-width: 100%;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n\n // Second header topic - title of the current page\n & + & {\n z-index: -1;\n transform: translateX(px2rem(25px));\n opacity: 0;\n transition:\n transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-25px));\n }\n }\n }\n\n // Header navigation title\n &__title {\n flex-grow: 1;\n height: px2rem(48px);\n margin-right: px2rem(8px);\n margin-left: px2rem(20px);\n font-size: px2rem(18px);\n line-height: px2rem(48px);\n\n // Header title in active state, i.e. page title is visible\n &[data-md-state=\"active\"] .md-header-nav__topic {\n z-index: -1;\n transform: translateX(px2rem(-25px));\n opacity: 0;\n transition:\n transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(25px));\n }\n\n // Second header topic - title of the current page\n & + .md-header-nav__topic {\n z-index: 0;\n transform: translateX(0);\n opacity: 1;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n pointer-events: initial;\n }\n }\n\n // Add ellipsis in case of overflowing text\n > .md-header-nav__ellipsis {\n position: relative;\n width: 100%;\n height: 100%;\n }\n }\n\n // Repository information container\n &__source {\n display: none;\n\n // [tablet landscape +]: Show repository information\n @include break-from-device(tablet landscape) {\n display: block;\n width: px2rem(234px);\n max-width: px2rem(234px);\n margin-left: px2rem(20px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(20px);\n margin-left: initial;\n }\n }\n\n // [screen +]: Adjust spacing of search bar\n @include break-from-device(screen) {\n margin-left: px2rem(28px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(28px);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Footer\n.md-footer {\n color: var(--md-footer-fg-color);\n background-color: var(--md-footer-bg-color);\n\n // [print]: Hide footer\n @media print {\n display: none;\n }\n}\n\n// Footer navigation\n.md-footer-nav {\n\n // Footer navigation wrapper\n &__inner {\n padding: px2rem(4px);\n overflow: auto;\n }\n\n // Footer link to previous and next page\n &__link {\n display: flex;\n padding-top: px2rem(28px);\n padding-bottom: px2rem(8px);\n transition: opacity 250ms;\n\n // [tablet +]: Adjust width to 50/50\n @include break-from-device(tablet) {\n width: 50%;\n }\n\n // Footer link on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Footer link to previous page\n &--prev {\n float: left;\n\n // [mobile -]: Adjust width to 25/75 and hide title\n @include break-to-device(mobile) {\n width: 25%;\n\n // Hide footer navigation title\n .md-footer-nav__title {\n display: none;\n }\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: right;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n\n // Footer link to next page\n &--next {\n float: right;\n text-align: right;\n\n // [mobile -]: Adjust width to 25/75\n @include break-to-device(mobile) {\n width: 75%;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n text-align: left;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n }\n\n // Footer navigation title\n &__title {\n position: relative;\n flex-grow: 1;\n max-width: calc(100% - #{px2rem(48px)});\n padding: 0 px2rem(20px);\n font-size: px2rem(18px);\n line-height: px2rem(48px);\n }\n\n // Footer navigation link button\n &__button {\n margin: px2rem(4px);\n padding: px2rem(8px);\n }\n\n // Footer navigation link direction (i.e. prev and next)\n &__direction {\n position: absolute;\n right: 0;\n left: 0;\n margin-top: px2rem(-20px);\n padding: 0 px2rem(20px);\n font-size: px2rem(12.8px);\n opacity: 0.7;\n }\n}\n\n// Footer metadata\n.md-footer-meta {\n background-color: var(--md-footer-bg-color--dark);\n\n // Footer metadata wrapper\n &__inner {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n padding: px2rem(4px);\n }\n\n // Lighten color for non-hovered text links\n html &.md-typeset a {\n color: var(--md-footer-fg-color--light);\n\n // Text link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-footer-fg-color);\n }\n }\n}\n\n// Footer copyright metadata\n.md-footer-copyright {\n width: 100%;\n margin: auto px2rem(12px);\n padding: px2rem(8px) 0;\n color: var(--md-footer-fg-color--lighter);\n font-size: px2rem(12.8px);\n\n // [tablet portrait +]: Show copyright and social links in one line\n @include break-from-device(tablet portrait) {\n width: auto;\n }\n\n // Footer copyright highlight - this is the upper part of the copyright and\n // theme information, which will include a darker color than the theme link\n &__highlight {\n color: var(--md-footer-fg-color--light);\n }\n}\n\n// Footer social metadata\n.md-footer-social {\n margin: 0 px2rem(8px);\n padding: px2rem(4px) 0 px2rem(12px);\n\n // [tablet portrait +]: Show copyright and social links in one line\n @include break-from-device(tablet portrait) {\n padding: px2rem(12px) 0;\n }\n\n // Footer social link\n &__link {\n display: inline-block;\n width: px2rem(32px);\n height: px2rem(32px);\n text-align: center;\n\n // Adjust line-height to match height for correct alignment\n &::before {\n line-height: 1.9;\n }\n\n // Fill icon with current color\n svg {\n max-height: px2rem(16px);\n vertical-align: -25%;\n fill: currentColor;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-nav-icon--prev: svg-load(\"@mdi/svg/svg/arrow-left.svg\");\n --md-nav-icon--next: svg-load(\"@mdi/svg/svg/chevron-right.svg\");\n --md-toc-icon: svg-load(\"@mdi/svg/svg/table-of-contents.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Navigation\n.md-nav {\n font-size: px2rem(14px);\n line-height: 1.3;\n\n // Navigation title\n &__title {\n display: block;\n padding: 0 px2rem(12px);\n overflow: hidden;\n font-weight: 700;\n text-overflow: ellipsis;\n\n // Navigaton button\n .md-nav__button {\n display: none;\n\n // Stretch images based on height, as it's the smaller dimension\n img {\n width: auto;\n height: 100%;\n }\n\n // Button with logo, pointing to `config.site_url`\n &.md-logo {\n\n // Image or icon\n img,\n svg {\n display: block;\n width: px2rem(48px);\n height: px2rem(48px);\n fill: currentColor;\n }\n }\n }\n }\n\n // Navigation list\n &__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n // Navigation item\n &__item {\n padding: 0 px2rem(12px);\n\n // Navigation item on level 2\n & & {\n padding-right: 0;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(12px);\n padding-left: 0;\n }\n }\n }\n\n // Navigation link\n &__link {\n display: block;\n margin-top: 0.625em;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n transition: color 125ms;\n scroll-snap-align: start;\n\n // Link in blurred state\n &[data-md-state=\"blur\"] {\n color: var(--md-default-fg-color--light);\n }\n\n // Active link\n .md-nav__item &--active {\n color: var(--md-typeset-a-color);\n }\n\n // Navigation link in nested list\n .md-nav__item--nested > & {\n color: inherit;\n }\n\n // Navigation link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Navigation link to table of contents\n .md-nav--primary &[for=\"__toc\"] {\n display: none;\n\n // Table of contents icon\n .md-icon::after {\n display: block;\n width: 100%;\n height: 100%;\n mask-image: var(--md-toc-icon);\n background-color: currentColor;\n }\n\n // Hide table of contents\n & ~ .md-nav {\n display: none;\n }\n }\n }\n\n // Repository information container\n &__source {\n display: none;\n }\n\n // [tablet -]: Layered navigation\n @include break-to-device(tablet) {\n\n // Primary and nested navigation\n &--primary,\n &--primary & {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--md-default-bg-color);\n }\n\n // Primary navigation\n &--primary {\n\n // Navigation title and item\n .md-nav__title,\n .md-nav__item {\n font-size: px2rem(16px);\n line-height: 1.5;\n }\n\n // Navigation title\n .md-nav__title {\n position: relative;\n height: px2rem(112px);\n padding: px2rem(60px) px2rem(16px) px2rem(4px);\n color: var(--md-default-fg-color--light);\n font-weight: 400;\n line-height: px2rem(48px);\n white-space: nowrap;\n background-color: var(--md-default-fg-color--lightest);\n cursor: pointer;\n\n // Navigation icon\n .md-nav__icon {\n position: absolute;\n top: px2rem(8px);\n left: px2rem(8px);\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n margin: px2rem(4px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(8px);\n left: initial;\n }\n\n // Navigation icon in link to previous level\n &::after {\n display: block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-nav-icon--prev);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n }\n\n // Navigation list\n ~ .md-nav__list {\n overflow-y: auto;\n background-color: var(--md-default-bg-color);\n box-shadow:\n 0 px2rem(1px) 0 var(--md-default-fg-color--lightest) inset;\n scroll-snap-type: y mandatory;\n touch-action: pan-y;\n\n // Omit border on first child\n > :first-child {\n border-top: 0;\n }\n }\n\n // Top-level navigation title\n &[for=\"__drawer\"] {\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n }\n\n // Button with logo, pointing to `config.site_url`\n .md-logo {\n position: absolute;\n top: px2rem(4px);\n left: px2rem(4px);\n display: block;\n margin: px2rem(4px);\n padding: px2rem(8px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(4px);\n left: initial;\n }\n }\n }\n\n // Navigation list\n .md-nav__list {\n flex: 1;\n }\n\n // Navigation item\n .md-nav__item {\n padding: 0;\n border-top: px2rem(1px) solid var(--md-default-fg-color--lightest);\n\n // Navigation link in nested navigation\n &--nested > .md-nav__link {\n padding-right: px2rem(48px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n }\n\n // Navigation link in active navigation\n &--active > .md-nav__link {\n color: var(--md-typeset-a-color);\n\n // Navigation link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n }\n\n // Navigation link\n .md-nav__link {\n position: relative;\n margin-top: 0;\n padding: px2rem(12px) px2rem(16px);\n\n // Navigation icon\n .md-nav__icon {\n position: absolute;\n top: 50%;\n right: px2rem(12px);\n width: px2rem(24px);\n height: px2rem(24px);\n margin-top: px2rem(-12px);\n color: inherit;\n font-size: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(12px);\n }\n\n // Navigation icon in link to next level\n &::after {\n display: block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-nav-icon--next);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n }\n }\n\n // Flip icon vertically\n .md-nav__icon {\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] &::after {\n transform: scale(-1);\n }\n }\n\n // Table of contents contained in primary navigation\n .md-nav--secondary {\n\n // Navigation link - omit unnecessary layering\n .md-nav__link {\n position: static;\n }\n\n // Navigation on level 2-6\n .md-nav {\n position: static;\n background-color: transparent;\n\n // Navigation link on level 3\n .md-nav__link {\n padding-left: px2rem(28px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(28px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 4\n .md-nav .md-nav__link {\n padding-left: px2rem(40px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(40px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 5\n .md-nav .md-nav .md-nav__link {\n padding-left: px2rem(52px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(52px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 6\n .md-nav .md-nav .md-nav .md-nav__link {\n padding-left: px2rem(64px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(64px);\n padding-left: initial;\n }\n }\n }\n }\n }\n\n // Table of contents\n &--secondary {\n background-color: transparent;\n }\n\n // Toggle for nested navigation\n &__toggle ~ & {\n display: flex;\n transform: translateX(100%);\n opacity: 0;\n transition:\n transform 250ms cubic-bezier(0.8, 0, 0.6, 1),\n opacity 125ms 50ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(-100%);\n }\n }\n\n // Show nested navigation when toggle is active\n &__toggle:checked ~ & {\n transform: translateX(0);\n opacity: 1;\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 125ms 125ms;\n\n // Navigation list\n > .md-nav__list {\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n }\n }\n }\n\n // [tablet portrait -]: Layered navigation with table of contents\n @include break-to-device(tablet portrait) {\n\n // Show link to table of contents\n &--primary &__link[for=\"__toc\"] {\n display: block;\n padding-right: px2rem(48px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n\n // Show table of contents icon\n .md-icon::after {\n content: \"\";\n }\n\n // Hide navigation link to current page\n + .md-nav__link {\n display: none;\n }\n\n // Show table of contents\n & ~ .md-nav {\n display: flex;\n }\n }\n\n // Repository information container\n &__source {\n display: block;\n padding: 0 px2rem(4px);\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color--dark);\n }\n }\n\n // [tablet landscape]: Layered navigation with table of contents\n @include break-at-device(tablet landscape) {\n\n // Show link to integrated table of contents\n &--integrated &__link[for=\"__toc\"] {\n display: block;\n padding-right: px2rem(48px);\n scroll-snap-align: initial;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n\n // Show table of contents icon\n .md-icon::after {\n content: \"\";\n }\n\n // Hide navigation link to current page\n + .md-nav__link {\n display: none;\n }\n\n // Show table of contents\n & ~ .md-nav {\n display: flex;\n }\n }\n }\n\n // [tablet landscape +]: Tree-like table of contents\n @include break-from-device(tablet landscape) {\n\n // Navigation title\n &--secondary &__title {\n\n // Adjust snapping behavior\n &[for=\"__toc\"] {\n scroll-snap-align: start;\n }\n\n // Hide navigation icon\n .md-nav__icon {\n display: none;\n }\n }\n }\n\n // [screen +]: Tree-like navigation\n @include break-from-device(screen) {\n transition: max-height 250ms cubic-bezier(0.86, 0, 0.07, 1);\n\n // Navigation title\n &--primary &__title {\n\n // Adjust snapping behavior\n &[for=\"__drawer\"] {\n scroll-snap-align: start;\n }\n\n // Hide navigation icon\n .md-nav__icon {\n display: none;\n }\n }\n\n // Hide toggle for nested navigation\n &__toggle ~ & {\n display: none;\n }\n\n // Show nested navigation when toggle is active or indeterminate\n &__toggle:checked ~ &,\n &__toggle:indeterminate ~ & {\n display: block;\n }\n\n // Hide navigation title in nested navigation\n &__item--nested > & > &__title {\n display: none;\n }\n\n // Navigation section\n &__item--section {\n display: block;\n margin: 1.25em 0;\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n\n // Hide navigation link, as sections are always expanded\n > .md-nav__link {\n display: none;\n }\n\n // Navigation\n > .md-nav {\n display: block;\n\n // Navigation title\n > .md-nav__title {\n display: block;\n padding: 0;\n pointer-events: none;\n scroll-snap-align: start;\n }\n\n // Adjust spacing on next level item\n > .md-nav__list > .md-nav__item {\n padding: 0;\n }\n }\n }\n\n // Navigation icon\n &__icon {\n float: right;\n width: px2rem(18px);\n height: px2rem(18px);\n transition: transform 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n transform: rotate(180deg);\n }\n\n // Navigation icon content\n &::after {\n display: inline-block;\n width: 100%;\n height: 100%;\n vertical-align: px2rem(-2px);\n background-color: currentColor;\n mask-image: var(--md-nav-icon--next);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Navigation icon - rotate icon when toggle is active or indeterminate\n .md-nav__item--nested .md-nav__toggle:checked ~ .md-nav__link &,\n .md-nav__item--nested .md-nav__toggle:indeterminate ~ .md-nav__link & {\n transform: rotate(90deg);\n }\n }\n\n // Modifier for when navigation tabs are rendered\n &--lifted {\n\n // Hide nested items on level 1 and site title\n > .md-nav__list > .md-nav__item--nested,\n > .md-nav__title {\n display: none;\n }\n\n // Hide level 1 items\n > .md-nav__list > .md-nav__item {\n display: none;\n\n // Active parent navigation item\n &--active {\n display: block;\n padding: 0;\n\n // Hide nested links\n > .md-nav__link {\n display: none;\n }\n\n // Show title and adjust spacing\n > .md-nav > .md-nav__title {\n display: block;\n padding: 0 px2rem(12px);\n pointer-events: none;\n scroll-snap-align: start;\n }\n }\n\n // Adjust spacing for navigation item on level 2\n > .md-nav__item {\n padding-right: px2rem(12px);\n }\n }\n\n // Hack: Always show active navigation tab on breakpoint screen, despite\n // of checkbox being checked or not. Fixes #1655.\n .md-nav[data-md-level=\"1\"] {\n display: block;\n }\n }\n\n // Modifier for when table of contents is rendered in primary navigation\n &--integrated &__link[for=\"__toc\"] ~ .md-nav {\n display: block;\n margin-bottom: 1.25em;\n border-left: px2rem(1px) solid var(--md-primary-fg-color);\n\n // Hide navigation title\n > .md-nav__title {\n display: none;\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-search-result-icon: svg-load(\"@mdi/svg/svg/file-search-outline.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Search\n.md-search {\n position: relative;\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n padding: px2rem(4px) 0;\n }\n\n // [no-js]: Hide search\n .no-js & {\n display: none;\n }\n\n // Search overlay\n &__overlay {\n z-index: 1;\n opacity: 0;\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n position: absolute;\n top: px2rem(4px);\n left: px2rem(-44px);\n width: px2rem(40px);\n height: px2rem(40px);\n overflow: hidden;\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(20px);\n transform-origin: center;\n transition:\n transform 300ms 100ms,\n opacity 200ms 200ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(-44px);\n left: initial;\n }\n\n // Show overlay when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n opacity: 1;\n transition:\n transform 400ms,\n opacity 100ms;\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n background-color: hsla(0, 0%, 0%, 0.54);\n cursor: pointer;\n transition:\n width 0ms 250ms,\n height 0ms 250ms,\n opacity 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n }\n\n // Show overlay when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n width: 100%;\n height: 100%;\n opacity: 1;\n transition:\n width 0ms,\n height 0ms,\n opacity 250ms;\n }\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n\n // [mobile portrait -]: Scale up 45 times\n @include break-to-device(mobile portrait) {\n transform: scale(45);\n }\n\n // [mobile landscape]: Scale up 60 times\n @include break-at-device(mobile landscape) {\n transform: scale(60);\n }\n\n // [tablet portrait]: Scale up 75 times\n @include break-at-device(tablet portrait) {\n transform: scale(75);\n }\n }\n }\n\n // Search wrapper\n &__inner {\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n position: fixed;\n top: 0;\n left: 100%;\n z-index: 2;\n width: 100%;\n height: 100%;\n transform: translateX(5%);\n opacity: 0;\n transition:\n right 0ms 300ms,\n left 0ms 300ms,\n transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 150ms 150ms;\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n left: 0;\n transform: translateX(0);\n opacity: 1;\n transition:\n right 0ms 0ms,\n left 0ms 0ms,\n transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms 150ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n }\n }\n\n // Adjust for right-to-left languages\n html [dir=\"rtl\"] & {\n right: 100%;\n left: initial;\n transform: translateX(-5%);\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n position: relative;\n float: right;\n width: px2rem(234px);\n padding: px2rem(2px) 0;\n transition: width 250ms cubic-bezier(0.1, 0.7, 0.1, 1);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n }\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n\n // [tablet landscape]: Omit overlaying header title\n @include break-at-device(tablet landscape) {\n width: px2rem(468px);\n }\n\n // [screen +]: Match width of content area\n @include break-from-device(screen) {\n width: px2rem(688px);\n }\n }\n }\n\n // Search form\n &__form {\n position: relative;\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n border-radius: px2rem(2px);\n }\n }\n\n // Search input\n &__input {\n position: relative;\n z-index: 2;\n padding: 0 px2rem(44px) 0 px2rem(72px);\n text-overflow: ellipsis;\n background-color: var(--md-default-bg-color);\n transition:\n color 250ms,\n background-color 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding: 0 px2rem(72px) 0 px2rem(44px);\n }\n\n // Search placeholder\n &::placeholder {\n transition: color 250ms;\n }\n\n // Search icon and placeholder\n ~ .md-search__icon,\n &::placeholder {\n color: var(--md-default-fg-color--light);\n }\n\n // Remove the \"x\" rendered by Internet Explorer\n &::-ms-clear {\n display: none;\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n width: 100%;\n height: px2rem(48px);\n font-size: px2rem(18px);\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n width: 100%;\n height: px2rem(36px);\n padding-left: px2rem(44px);\n color: inherit;\n font-size: px2rem(16px);\n background-color: hsla(0, 0%, 0%, 0.26);\n border-radius: px2rem(2px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n }\n\n // Search icon\n + .md-search__icon {\n color: var(--md-primary-bg-color);\n }\n\n // Search placeholder\n &::placeholder {\n color: var(--md-primary-bg-color--light);\n }\n\n // Search input on hover\n &:hover {\n background-color: hsla(0, 0%, 100%, 0.12);\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n color: var(--md-default-fg-color);\n text-overflow: clip;\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(2px) px2rem(2px) 0 0;\n\n // Search icon and placeholder\n + .md-search__icon,\n &::placeholder {\n color: var(--md-default-fg-color--light);\n }\n }\n }\n }\n\n // Search icon\n &__icon {\n position: absolute;\n z-index: 2;\n width: px2rem(24px);\n height: px2rem(24px);\n cursor: pointer;\n transition:\n color 250ms,\n opacity 250ms;\n\n // Search icon on hover\n &:hover {\n opacity: 0.7;\n }\n\n // Search focus button\n &[for=\"__search\"] {\n top: px2rem(6px);\n left: px2rem(10px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(10px);\n left: initial;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(12px);\n left: px2rem(16px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(16px);\n left: initial;\n }\n\n // Hide the magnifying glass\n svg:first-child {\n display: none;\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n pointer-events: none;\n\n // Hide the back arrow\n svg:last-child {\n display: none;\n }\n }\n }\n\n // Search reset button\n &[type=\"reset\"] {\n top: px2rem(6px);\n right: px2rem(10px);\n transform: scale(0.75);\n opacity: 0;\n transition:\n transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(10px);\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(12px);\n right: px2rem(16px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(16px);\n }\n }\n\n // Show reset button when search is active and input non-empty\n [data-md-toggle=\"search\"]:checked ~ .md-header\n .md-search__input:valid ~ & {\n transform: scale(1);\n opacity: 1;\n pointer-events: initial;\n\n // Search focus icon\n &:hover {\n opacity: 0.7;\n }\n }\n }\n }\n\n // Search output\n &__output {\n position: absolute;\n z-index: 1;\n width: 100%;\n overflow: hidden;\n border-radius: 0 0 px2rem(2px) px2rem(2px);\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(48px);\n bottom: 0;\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n top: px2rem(38px);\n opacity: 0;\n transition: opacity 400ms;\n\n // Show output when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n @include z-depth(6);\n\n opacity: 1;\n }\n }\n }\n\n // Search scroll wrapper\n &__scrollwrap {\n height: 100%;\n overflow-y: auto;\n background-color: var(--md-default-bg-color);\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n scroll-snap-type: y mandatory;\n touch-action: pan-y;\n\n // Mitigiate excessive repaints on non-retina devices\n @media (max-resolution: 1dppx) {\n transform: translateZ(0);\n }\n\n // [tablet landscape]: Set fixed width to omit unnecessary reflow\n @include break-at-device(tablet landscape) {\n width: px2rem(468px);\n }\n\n // [screen +]: Set fixed width to omit unnecessary reflow\n @include break-from-device(screen) {\n width: px2rem(688px);\n }\n\n // [tablet landscape +]: Limit height to viewport\n @include break-from-device(tablet landscape) {\n max-height: 0;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Show scroll wrapper when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n max-height: 75vh;\n }\n\n // Search scroll wrapper on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n }\n}\n\n// Search result\n.md-search-result {\n color: var(--md-default-fg-color);\n word-break: break-word;\n\n // Search result metadata\n &__meta {\n padding: 0 px2rem(16px);\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n line-height: px2rem(36px);\n background-color: var(--md-default-fg-color--lightest);\n scroll-snap-align: start;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: initial;\n }\n }\n }\n\n // Search result list\n &__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n // Search result item\n &__item {\n box-shadow: 0 px2rem(-1px) 0 var(--md-default-fg-color--lightest);\n\n // Omit border on first child\n &:first-child {\n box-shadow: none;\n }\n }\n\n // Search result link\n &__link {\n display: block;\n outline: none;\n transition: background-color 250ms;\n scroll-snap-align: start;\n\n // Search result link on focus/hover\n &:focus,\n &:hover {\n background-color: var(--md-accent-fg-color--transparent);\n }\n\n // Adjust spacing on last child of last link\n &:last-child p:last-child {\n margin-bottom: px2rem(12px);\n }\n }\n\n // Search result more link\n &__more summary {\n display: block;\n padding: px2em(12px) px2rem(16px);\n color: var(--md-typeset-a-color);\n font-size: px2rem(12.8px);\n outline: 0;\n cursor: pointer;\n transition:\n color 250ms,\n background-color 250ms;\n scroll-snap-align: start;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: px2rem(16px);\n }\n }\n\n // Search result more link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n background-color: var(--md-accent-fg-color--transparent);\n }\n\n // Hide native details marker\n &::-webkit-details-marker {\n display: none;\n }\n\n // Adjust transparency of less relevant results\n & ~ * > * {\n opacity: 0.65;\n }\n }\n\n // Search result article\n &__article {\n position: relative;\n padding: 0 px2rem(16px);\n overflow: hidden;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: px2rem(16px);\n }\n }\n\n // Search result article document\n &--document {\n\n // Search result title\n .md-search-result__title {\n margin: px2rem(11px) 0;\n font-weight: 400;\n font-size: px2rem(16px);\n line-height: 1.4;\n }\n }\n }\n\n // Search result icon\n &__icon {\n position: absolute;\n left: 0;\n width: px2rem(24px);\n height: px2rem(24px);\n margin: px2rem(10px);\n color: var(--md-default-fg-color--light);\n\n // [tablet portrait -]: Hide icon\n @include break-to-device(tablet portrait) {\n display: none;\n }\n\n // Search result icon content\n &::after {\n display: inline-block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-search-result-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n\n // Flip icon vertically\n &::after {\n transform: scaleX(-1);\n }\n }\n }\n\n // Search result title\n &__title {\n margin: 0.5em 0;\n font-weight: 700;\n font-size: px2rem(12.8px);\n line-height: 1.6;\n }\n\n // Search result teaser\n &__teaser {\n display: -webkit-box;\n max-height: px2rem(40px);\n margin: 0.5em 0;\n overflow: hidden;\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n line-height: 1.6;\n text-overflow: ellipsis;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n\n // [mobile -]: Adjust number of lines\n @include break-to-device(mobile) {\n max-height: px2rem(60px);\n -webkit-line-clamp: 3;\n }\n\n // [tablet landscape]: Adjust number of lines\n @include break-at-device(tablet landscape) {\n max-height: px2rem(60px);\n -webkit-line-clamp: 3;\n }\n\n // Search term highlighting\n mark {\n text-decoration: underline;\n background-color: transparent;\n }\n }\n\n // Search result terms\n &__terms {\n margin: 0.5em 0;\n font-size: px2rem(12.8px);\n font-style: italic;\n }\n\n // Search term highlighting\n mark {\n color: var(--md-accent-fg-color);\n background-color: transparent;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Sidebar\n.md-sidebar {\n position: sticky;\n top: px2rem(48px);\n flex-shrink: 0;\n align-self: flex-start;\n width: px2rem(242px);\n height: 0;\n padding: px2rem(24px) 0;\n\n // [print]: Hide sidebar\n @media print {\n display: none;\n }\n\n // [tablet -]: Show navigation as drawer\n @include break-to-device(tablet) {\n\n // Primary sidebar with navigation\n &--primary {\n position: fixed;\n top: 0;\n left: px2rem(-242px);\n z-index: 3;\n display: block;\n width: px2rem(242px);\n height: 100%;\n background-color: var(--md-default-bg-color);\n transform: translateX(0);\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n box-shadow 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(-242px);\n left: initial;\n }\n\n // Show sidebar when drawer is active\n [data-md-toggle=\"drawer\"]:checked ~ .md-container & {\n @include z-depth(8);\n\n transform: translateX(px2rem(242px));\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-242px));\n }\n }\n\n // Stretch scroll wrapper for primary sidebar\n .md-sidebar__scrollwrap {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n margin: 0;\n scroll-snap-type: none;\n overflow: hidden;\n }\n }\n }\n\n // [screen +]: Show navigation as sidebar\n @include break-from-device(screen) {\n height: 0;\n\n // [no-js]: Switch to native sticky behavior\n .no-js & {\n height: auto;\n }\n }\n\n // Secondary sidebar with table of contents\n &--secondary {\n display: none;\n order: 2;\n\n // [tablet landscape +]: Show table of contents as sidebar\n @include break-from-device(tablet landscape) {\n height: 0;\n\n // [no-js]: Switch to native sticky behavior\n .no-js & {\n height: auto;\n }\n\n // Sidebar is visible\n &:not([hidden]) {\n display: block;\n }\n\n // Ensure smooth scrolling on iOS\n .md-sidebar__scrollwrap {\n touch-action: pan-y;\n }\n }\n }\n\n // Sidebar scroll wrapper\n &__scrollwrap {\n margin: 0 px2rem(4px);\n overflow-y: auto;\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n // Hack: Chrome 81+ exhibits a strange bug, where it scrolls the container\n // to the bottom if `scroll-snap-type` is set on the initial render. For\n // this reason, we disable scroll snapping until this is resolved (#1667).\n // scroll-snap-type: y mandatory;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Sidebar scroll wrapper on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n}\n\n// [tablet -]: Show overlay on active drawer\n@include break-to-device(tablet) {\n\n // Sidebar overlay\n .md-overlay {\n position: fixed;\n top: 0;\n z-index: 3;\n width: 0;\n height: 0;\n background-color: hsla(0, 0%, 0%, 0.54);\n opacity: 0;\n transition:\n width 0ms 250ms,\n height 0ms 250ms,\n opacity 250ms;\n\n // Show overlay when drawer is active\n [data-md-toggle=\"drawer\"]:checked ~ & {\n width: 100%;\n height: 100%;\n opacity: 1;\n transition:\n width 0ms,\n height 0ms,\n opacity 250ms;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Keyframes\n// ----------------------------------------------------------------------------\n\n// Show source facts\n@keyframes md-source__facts--done {\n 0% {\n height: 0;\n }\n 100% {\n height: px2rem(13px);\n }\n}\n\n// Show source fact\n@keyframes md-source__fact--done {\n 0% {\n transform: translateY(100%);\n opacity: 0;\n }\n 50% {\n opacity: 0;\n }\n 100% {\n transform: translateY(0%);\n opacity: 1;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Repository information\n.md-source {\n display: block;\n font-size: px2rem(13px);\n line-height: 1.2;\n white-space: nowrap;\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n transition: opacity 250ms;\n\n // Repository information on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Repository icon\n &__icon {\n display: inline-block;\n width: px2rem(48px);\n height: px2rem(48px);\n vertical-align: middle;\n\n // Align with margin only (as opposed to normal button alignment)\n svg {\n margin-top: px2rem(12px);\n margin-left: px2rem(12px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(12px);\n margin-left: initial;\n }\n }\n\n // Adjust spacing if icon is present\n + .md-source__repository {\n margin-left: px2rem(-40px);\n padding-left: px2rem(40px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(-40px);\n margin-left: initial;\n padding-right: px2rem(40px);\n padding-left: initial;\n }\n }\n }\n\n // Repository name\n &__repository {\n display: inline-block;\n max-width: calc(100% - #{px2rem(24px)});\n margin-left: px2rem(12px);\n overflow: hidden;\n font-weight: 700;\n text-overflow: ellipsis;\n vertical-align: middle;\n }\n\n // Repository facts\n &__facts {\n margin: 0;\n padding: 0;\n overflow: hidden;\n font-weight: 700;\n font-size: px2rem(11px);\n list-style-type: none;\n opacity: 0.75;\n\n // Show after the data was loaded\n [data-md-state=\"done\"] & {\n animation: md-source__facts--done 250ms ease-in;\n }\n }\n\n // Repository fact\n &__fact {\n float: left;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: right;\n }\n\n // Show after the data was loaded\n [data-md-state=\"done\"] & {\n animation: md-source__fact--done 400ms ease-out;\n }\n\n // Middle dot before fact\n &::before {\n margin: 0 px2rem(2px);\n content: \"\\00B7\";\n }\n\n // Remove middle dot on first fact\n &:first-child::before {\n display: none;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Navigation tabs\n.md-tabs {\n width: 100%;\n overflow: auto;\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n transition: background-color 250ms;\n\n // [print]: Hide tabs\n @media print {\n display: none;\n }\n\n // [tablet -]: Hide tabs\n @include break-to-device(tablet) {\n display: none;\n }\n\n // Tabs in hidden state, i.e. when scrolling down\n &[data-md-state=\"hidden\"] {\n pointer-events: none;\n }\n\n // Navigation tabs list\n &__list {\n margin: 0;\n margin-left: px2rem(4px);\n padding: 0;\n white-space: nowrap;\n list-style: none;\n contain: content;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(4px);\n margin-left: initial;\n }\n }\n\n // Navigation tabs item\n &__item {\n display: inline-block;\n height: px2rem(48px);\n padding-right: px2rem(12px);\n padding-left: px2rem(12px);\n }\n\n // Navigation tabs link - could be defined as block elements and aligned via\n // line height, but this would imply more repaints when scrolling\n &__link {\n display: block;\n margin-top: px2rem(16px);\n font-size: px2rem(14px);\n // Hack: save a repaint when tabs are appearing on scrolling up\n backface-visibility: hidden;\n opacity: 0.7;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 250ms;\n\n // Active link and link on focus/hover\n &--active,\n &:focus,\n &:hover {\n color: inherit;\n opacity: 1;\n }\n\n // Delay transitions by a small amount\n @for $i from 2 through 16 {\n .md-tabs__item:nth-child(#{$i}) & {\n transition-delay: 20ms * ($i - 1);\n }\n }\n\n // Hide tabs upon scrolling - disable transition to minimizes repaints\n // while scrolling down, while scrolling up seems to be okay\n .md-tabs[data-md-state=\"hidden\"] & {\n transform: translateY(50%);\n opacity: 0;\n transition:\n transform 0ms 100ms,\n opacity 100ms;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n/// Admonition flavours\n$admonitions: (\n note: pencil $clr-blue-a200,\n abstract summary tldr: text-subject $clr-light-blue-a400,\n info todo: information $clr-cyan-a700,\n tip hint important: fire $clr-teal-a700,\n success check done: check-circle $clr-green-a700,\n question help faq: help-circle $clr-light-green-a700,\n warning caution attention: alert $clr-orange-a400,\n failure fail missing: close-circle $clr-red-a200,\n danger error: flash-circle $clr-red-a400,\n bug: bug $clr-pink-a400,\n example: format-list-numbered $clr-deep-purple-a400,\n quote cite: format-quote-close $clr-grey\n) !default;\n\n// ----------------------------------------------------------------------------\n// Rules: layout\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n @each $names, $props in $admonitions {\n --md-admonition-icon--#{nth($names, 1)}: svg-load(\n \"@mdi/svg/svg/#{nth($props, 1)}.svg\"\n );\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Admonition\n .admonition {\n margin: px2em(20px, 12.8px) 0;\n padding: 0 px2rem(12px);\n overflow: hidden;\n color: var(--md-admonition-fg-color);\n font-size: px2rem(12.8px);\n page-break-inside: avoid;\n background-color: var(--md-admonition-bg-color);\n border-left: px2rem(4px) solid $clr-blue-a200;\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(4px) px2rem(10px) hsla(0, 0%, 0%, 0.05),\n 0 px2rem(0.5px) px2rem(1px) hsla(0, 0%, 0%, 0.05);\n\n // [print]: Omit shadow as it may lead to rendering errors\n @media print {\n box-shadow: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n border-right: px2rem(4px) solid $clr-blue-a200;\n border-left: none;\n }\n\n // Adjust spacing for nested admonitions\n .admonition {\n margin: 1em 0;\n }\n\n // Adjust spacing for contained table wrappers\n .md-typeset__scrollwrap {\n margin: 1em px2rem(-12px);\n }\n\n // Adjust spacing for contained tables\n .md-typeset__table {\n padding: 0 px2rem(12px);\n }\n\n // Adjust spacing for single-child tabbed block container\n > .tabbed-set:only-child {\n margin-top: 0;\n }\n\n // Adjust spacing on last child\n html & > :last-child {\n margin-bottom: px2rem(12px);\n }\n }\n\n // Admonition title\n .admonition-title {\n position: relative;\n margin: 0 px2rem(-12px) 0 px2rem(-16px);\n padding: px2rem(8px) px2rem(12px) px2rem(8px) px2rem(40px);\n font-weight: 700;\n background-color: transparentize($clr-blue-a200, 0.9);\n border-left: px2rem(4px) solid $clr-blue-a200;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin: 0 px2rem(-16px) 0 px2rem(-12px);\n padding: px2rem(8px) px2rem(40px) px2rem(8px) px2rem(12px);\n border-right: px2rem(4px) solid $clr-blue-a200;\n border-left: none;\n }\n\n // Adjust spacing for title-only admonitions\n html &:last-child {\n margin-bottom: 0;\n }\n\n // Admonition icon\n &::before {\n position: absolute;\n left: px2rem(12px);\n width: px2rem(20px);\n height: px2rem(20px);\n background-color: $clr-blue-a200;\n mask-image: var(--md-admonition-icon--note);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(12px);\n left: initial;\n }\n }\n\n // Omit background on inline code blocks, as they don't go well with the\n // pastelly tones applied to admonition titles\n code {\n margin: initial;\n padding: initial;\n color: currentColor;\n background-color: transparent;\n border-radius: initial;\n box-shadow: none;\n }\n\n // Adjust spacing on last tabbed block container child - if the tabbed\n // block container is the sole child, it looks better to omit the margin\n + .tabbed-set:last-child {\n margin-top: 0;\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: flavours\n// ----------------------------------------------------------------------------\n\n@each $names, $props in $admonitions {\n $name: nth($names, 1);\n $tint: nth($props, 2);\n\n // Admonition flavour\n .md-typeset .admonition.#{$name} {\n border-color: $tint;\n }\n\n // Admonition flavour title\n .md-typeset .#{$name} > .admonition-title {\n background-color: transparentize($tint, 0.9);\n border-color: $tint;\n\n // Admonition icon\n &::before {\n background-color: $tint;\n mask-image: var(--md-admonition-icon--#{$name});\n mask-repeat: no-repeat;\n mask-size: contain;\n }\n }\n\n // Define synonyms for flavours\n @if length($names) > 1 {\n @for $n from 2 through length($names) {\n .#{nth($names, $n)} {\n @extend .#{$name};\n }\n }\n }\n}\n","// ==========================================================================\n//\n// Name: UI Color Palette\n// Description: The color palette of material design.\n// Version: 2.3.1\n//\n// Author: Denis Malinochkin\n// Git: https://github.com/mrmlnc/material-color\n//\n// twitter: @mrmlnc\n//\n// ==========================================================================\n\n\n//\n// List of base colors\n//\n\n// $clr-red\n// $clr-pink\n// $clr-purple\n// $clr-deep-purple\n// $clr-indigo\n// $clr-blue\n// $clr-light-blue\n// $clr-cyan\n// $clr-teal\n// $clr-green\n// $clr-light-green\n// $clr-lime\n// $clr-yellow\n// $clr-amber\n// $clr-orange\n// $clr-deep-orange\n// $clr-brown\n// $clr-grey\n// $clr-blue-grey\n// $clr-black\n// $clr-white\n\n\n//\n// Red\n//\n\n$clr-red-list: (\n \"base\": #f44336,\n \"50\": #ffebee,\n \"100\": #ffcdd2,\n \"200\": #ef9a9a,\n \"300\": #e57373,\n \"400\": #ef5350,\n \"500\": #f44336,\n \"600\": #e53935,\n \"700\": #d32f2f,\n \"800\": #c62828,\n \"900\": #b71c1c,\n \"a100\": #ff8a80,\n \"a200\": #ff5252,\n \"a400\": #ff1744,\n \"a700\": #d50000\n);\n\n$clr-red: map-get($clr-red-list, \"base\");\n\n$clr-red-50: map-get($clr-red-list, \"50\");\n$clr-red-100: map-get($clr-red-list, \"100\");\n$clr-red-200: map-get($clr-red-list, \"200\");\n$clr-red-300: map-get($clr-red-list, \"300\");\n$clr-red-400: map-get($clr-red-list, \"400\");\n$clr-red-500: map-get($clr-red-list, \"500\");\n$clr-red-600: map-get($clr-red-list, \"600\");\n$clr-red-700: map-get($clr-red-list, \"700\");\n$clr-red-800: map-get($clr-red-list, \"800\");\n$clr-red-900: map-get($clr-red-list, \"900\");\n$clr-red-a100: map-get($clr-red-list, \"a100\");\n$clr-red-a200: map-get($clr-red-list, \"a200\");\n$clr-red-a400: map-get($clr-red-list, \"a400\");\n$clr-red-a700: map-get($clr-red-list, \"a700\");\n\n\n//\n// Pink\n//\n\n$clr-pink-list: (\n \"base\": #e91e63,\n \"50\": #fce4ec,\n \"100\": #f8bbd0,\n \"200\": #f48fb1,\n \"300\": #f06292,\n \"400\": #ec407a,\n \"500\": #e91e63,\n \"600\": #d81b60,\n \"700\": #c2185b,\n \"800\": #ad1457,\n \"900\": #880e4f,\n \"a100\": #ff80ab,\n \"a200\": #ff4081,\n \"a400\": #f50057,\n \"a700\": #c51162\n);\n\n$clr-pink: map-get($clr-pink-list, \"base\");\n\n$clr-pink-50: map-get($clr-pink-list, \"50\");\n$clr-pink-100: map-get($clr-pink-list, \"100\");\n$clr-pink-200: map-get($clr-pink-list, \"200\");\n$clr-pink-300: map-get($clr-pink-list, \"300\");\n$clr-pink-400: map-get($clr-pink-list, \"400\");\n$clr-pink-500: map-get($clr-pink-list, \"500\");\n$clr-pink-600: map-get($clr-pink-list, \"600\");\n$clr-pink-700: map-get($clr-pink-list, \"700\");\n$clr-pink-800: map-get($clr-pink-list, \"800\");\n$clr-pink-900: map-get($clr-pink-list, \"900\");\n$clr-pink-a100: map-get($clr-pink-list, \"a100\");\n$clr-pink-a200: map-get($clr-pink-list, \"a200\");\n$clr-pink-a400: map-get($clr-pink-list, \"a400\");\n$clr-pink-a700: map-get($clr-pink-list, \"a700\");\n\n\n//\n// Purple\n//\n\n$clr-purple-list: (\n \"base\": #9c27b0,\n \"50\": #f3e5f5,\n \"100\": #e1bee7,\n \"200\": #ce93d8,\n \"300\": #ba68c8,\n \"400\": #ab47bc,\n \"500\": #9c27b0,\n \"600\": #8e24aa,\n \"700\": #7b1fa2,\n \"800\": #6a1b9a,\n \"900\": #4a148c,\n \"a100\": #ea80fc,\n \"a200\": #e040fb,\n \"a400\": #d500f9,\n \"a700\": #aa00ff\n);\n\n$clr-purple: map-get($clr-purple-list, \"base\");\n\n$clr-purple-50: map-get($clr-purple-list, \"50\");\n$clr-purple-100: map-get($clr-purple-list, \"100\");\n$clr-purple-200: map-get($clr-purple-list, \"200\");\n$clr-purple-300: map-get($clr-purple-list, \"300\");\n$clr-purple-400: map-get($clr-purple-list, \"400\");\n$clr-purple-500: map-get($clr-purple-list, \"500\");\n$clr-purple-600: map-get($clr-purple-list, \"600\");\n$clr-purple-700: map-get($clr-purple-list, \"700\");\n$clr-purple-800: map-get($clr-purple-list, \"800\");\n$clr-purple-900: map-get($clr-purple-list, \"900\");\n$clr-purple-a100: map-get($clr-purple-list, \"a100\");\n$clr-purple-a200: map-get($clr-purple-list, \"a200\");\n$clr-purple-a400: map-get($clr-purple-list, \"a400\");\n$clr-purple-a700: map-get($clr-purple-list, \"a700\");\n\n\n//\n// Deep purple\n//\n\n$clr-deep-purple-list: (\n \"base\": #673ab7,\n \"50\": #ede7f6,\n \"100\": #d1c4e9,\n \"200\": #b39ddb,\n \"300\": #9575cd,\n \"400\": #7e57c2,\n \"500\": #673ab7,\n \"600\": #5e35b1,\n \"700\": #512da8,\n \"800\": #4527a0,\n \"900\": #311b92,\n \"a100\": #b388ff,\n \"a200\": #7c4dff,\n \"a400\": #651fff,\n \"a700\": #6200ea\n);\n\n$clr-deep-purple: map-get($clr-deep-purple-list, \"base\");\n\n$clr-deep-purple-50: map-get($clr-deep-purple-list, \"50\");\n$clr-deep-purple-100: map-get($clr-deep-purple-list, \"100\");\n$clr-deep-purple-200: map-get($clr-deep-purple-list, \"200\");\n$clr-deep-purple-300: map-get($clr-deep-purple-list, \"300\");\n$clr-deep-purple-400: map-get($clr-deep-purple-list, \"400\");\n$clr-deep-purple-500: map-get($clr-deep-purple-list, \"500\");\n$clr-deep-purple-600: map-get($clr-deep-purple-list, \"600\");\n$clr-deep-purple-700: map-get($clr-deep-purple-list, \"700\");\n$clr-deep-purple-800: map-get($clr-deep-purple-list, \"800\");\n$clr-deep-purple-900: map-get($clr-deep-purple-list, \"900\");\n$clr-deep-purple-a100: map-get($clr-deep-purple-list, \"a100\");\n$clr-deep-purple-a200: map-get($clr-deep-purple-list, \"a200\");\n$clr-deep-purple-a400: map-get($clr-deep-purple-list, \"a400\");\n$clr-deep-purple-a700: map-get($clr-deep-purple-list, \"a700\");\n\n\n//\n// Indigo\n//\n\n$clr-indigo-list: (\n \"base\": #3f51b5,\n \"50\": #e8eaf6,\n \"100\": #c5cae9,\n \"200\": #9fa8da,\n \"300\": #7986cb,\n \"400\": #5c6bc0,\n \"500\": #3f51b5,\n \"600\": #3949ab,\n \"700\": #303f9f,\n \"800\": #283593,\n \"900\": #1a237e,\n \"a100\": #8c9eff,\n \"a200\": #536dfe,\n \"a400\": #3d5afe,\n \"a700\": #304ffe\n);\n\n$clr-indigo: map-get($clr-indigo-list, \"base\");\n\n$clr-indigo-50: map-get($clr-indigo-list, \"50\");\n$clr-indigo-100: map-get($clr-indigo-list, \"100\");\n$clr-indigo-200: map-get($clr-indigo-list, \"200\");\n$clr-indigo-300: map-get($clr-indigo-list, \"300\");\n$clr-indigo-400: map-get($clr-indigo-list, \"400\");\n$clr-indigo-500: map-get($clr-indigo-list, \"500\");\n$clr-indigo-600: map-get($clr-indigo-list, \"600\");\n$clr-indigo-700: map-get($clr-indigo-list, \"700\");\n$clr-indigo-800: map-get($clr-indigo-list, \"800\");\n$clr-indigo-900: map-get($clr-indigo-list, \"900\");\n$clr-indigo-a100: map-get($clr-indigo-list, \"a100\");\n$clr-indigo-a200: map-get($clr-indigo-list, \"a200\");\n$clr-indigo-a400: map-get($clr-indigo-list, \"a400\");\n$clr-indigo-a700: map-get($clr-indigo-list, \"a700\");\n\n\n//\n// Blue\n//\n\n$clr-blue-list: (\n \"base\": #2196f3,\n \"50\": #e3f2fd,\n \"100\": #bbdefb,\n \"200\": #90caf9,\n \"300\": #64b5f6,\n \"400\": #42a5f5,\n \"500\": #2196f3,\n \"600\": #1e88e5,\n \"700\": #1976d2,\n \"800\": #1565c0,\n \"900\": #0d47a1,\n \"a100\": #82b1ff,\n \"a200\": #448aff,\n \"a400\": #2979ff,\n \"a700\": #2962ff\n);\n\n$clr-blue: map-get($clr-blue-list, \"base\");\n\n$clr-blue-50: map-get($clr-blue-list, \"50\");\n$clr-blue-100: map-get($clr-blue-list, \"100\");\n$clr-blue-200: map-get($clr-blue-list, \"200\");\n$clr-blue-300: map-get($clr-blue-list, \"300\");\n$clr-blue-400: map-get($clr-blue-list, \"400\");\n$clr-blue-500: map-get($clr-blue-list, \"500\");\n$clr-blue-600: map-get($clr-blue-list, \"600\");\n$clr-blue-700: map-get($clr-blue-list, \"700\");\n$clr-blue-800: map-get($clr-blue-list, \"800\");\n$clr-blue-900: map-get($clr-blue-list, \"900\");\n$clr-blue-a100: map-get($clr-blue-list, \"a100\");\n$clr-blue-a200: map-get($clr-blue-list, \"a200\");\n$clr-blue-a400: map-get($clr-blue-list, \"a400\");\n$clr-blue-a700: map-get($clr-blue-list, \"a700\");\n\n\n//\n// Light Blue\n//\n\n$clr-light-blue-list: (\n \"base\": #03a9f4,\n \"50\": #e1f5fe,\n \"100\": #b3e5fc,\n \"200\": #81d4fa,\n \"300\": #4fc3f7,\n \"400\": #29b6f6,\n \"500\": #03a9f4,\n \"600\": #039be5,\n \"700\": #0288d1,\n \"800\": #0277bd,\n \"900\": #01579b,\n \"a100\": #80d8ff,\n \"a200\": #40c4ff,\n \"a400\": #00b0ff,\n \"a700\": #0091ea\n);\n\n$clr-light-blue: map-get($clr-light-blue-list, \"base\");\n\n$clr-light-blue-50: map-get($clr-light-blue-list, \"50\");\n$clr-light-blue-100: map-get($clr-light-blue-list, \"100\");\n$clr-light-blue-200: map-get($clr-light-blue-list, \"200\");\n$clr-light-blue-300: map-get($clr-light-blue-list, \"300\");\n$clr-light-blue-400: map-get($clr-light-blue-list, \"400\");\n$clr-light-blue-500: map-get($clr-light-blue-list, \"500\");\n$clr-light-blue-600: map-get($clr-light-blue-list, \"600\");\n$clr-light-blue-700: map-get($clr-light-blue-list, \"700\");\n$clr-light-blue-800: map-get($clr-light-blue-list, \"800\");\n$clr-light-blue-900: map-get($clr-light-blue-list, \"900\");\n$clr-light-blue-a100: map-get($clr-light-blue-list, \"a100\");\n$clr-light-blue-a200: map-get($clr-light-blue-list, \"a200\");\n$clr-light-blue-a400: map-get($clr-light-blue-list, \"a400\");\n$clr-light-blue-a700: map-get($clr-light-blue-list, \"a700\");\n\n\n//\n// Cyan\n//\n\n$clr-cyan-list: (\n \"base\": #00bcd4,\n \"50\": #e0f7fa,\n \"100\": #b2ebf2,\n \"200\": #80deea,\n \"300\": #4dd0e1,\n \"400\": #26c6da,\n \"500\": #00bcd4,\n \"600\": #00acc1,\n \"700\": #0097a7,\n \"800\": #00838f,\n \"900\": #006064,\n \"a100\": #84ffff,\n \"a200\": #18ffff,\n \"a400\": #00e5ff,\n \"a700\": #00b8d4\n);\n\n$clr-cyan: map-get($clr-cyan-list, \"base\");\n\n$clr-cyan-50: map-get($clr-cyan-list, \"50\");\n$clr-cyan-100: map-get($clr-cyan-list, \"100\");\n$clr-cyan-200: map-get($clr-cyan-list, \"200\");\n$clr-cyan-300: map-get($clr-cyan-list, \"300\");\n$clr-cyan-400: map-get($clr-cyan-list, \"400\");\n$clr-cyan-500: map-get($clr-cyan-list, \"500\");\n$clr-cyan-600: map-get($clr-cyan-list, \"600\");\n$clr-cyan-700: map-get($clr-cyan-list, \"700\");\n$clr-cyan-800: map-get($clr-cyan-list, \"800\");\n$clr-cyan-900: map-get($clr-cyan-list, \"900\");\n$clr-cyan-a100: map-get($clr-cyan-list, \"a100\");\n$clr-cyan-a200: map-get($clr-cyan-list, \"a200\");\n$clr-cyan-a400: map-get($clr-cyan-list, \"a400\");\n$clr-cyan-a700: map-get($clr-cyan-list, \"a700\");\n\n\n//\n// Teal\n//\n\n$clr-teal-list: (\n \"base\": #009688,\n \"50\": #e0f2f1,\n \"100\": #b2dfdb,\n \"200\": #80cbc4,\n \"300\": #4db6ac,\n \"400\": #26a69a,\n \"500\": #009688,\n \"600\": #00897b,\n \"700\": #00796b,\n \"800\": #00695c,\n \"900\": #004d40,\n \"a100\": #a7ffeb,\n \"a200\": #64ffda,\n \"a400\": #1de9b6,\n \"a700\": #00bfa5\n);\n\n$clr-teal: map-get($clr-teal-list, \"base\");\n\n$clr-teal-50: map-get($clr-teal-list, \"50\");\n$clr-teal-100: map-get($clr-teal-list, \"100\");\n$clr-teal-200: map-get($clr-teal-list, \"200\");\n$clr-teal-300: map-get($clr-teal-list, \"300\");\n$clr-teal-400: map-get($clr-teal-list, \"400\");\n$clr-teal-500: map-get($clr-teal-list, \"500\");\n$clr-teal-600: map-get($clr-teal-list, \"600\");\n$clr-teal-700: map-get($clr-teal-list, \"700\");\n$clr-teal-800: map-get($clr-teal-list, \"800\");\n$clr-teal-900: map-get($clr-teal-list, \"900\");\n$clr-teal-a100: map-get($clr-teal-list, \"a100\");\n$clr-teal-a200: map-get($clr-teal-list, \"a200\");\n$clr-teal-a400: map-get($clr-teal-list, \"a400\");\n$clr-teal-a700: map-get($clr-teal-list, \"a700\");\n\n\n//\n// Green\n//\n\n$clr-green-list: (\n \"base\": #4caf50,\n \"50\": #e8f5e9,\n \"100\": #c8e6c9,\n \"200\": #a5d6a7,\n \"300\": #81c784,\n \"400\": #66bb6a,\n \"500\": #4caf50,\n \"600\": #43a047,\n \"700\": #388e3c,\n \"800\": #2e7d32,\n \"900\": #1b5e20,\n \"a100\": #b9f6ca,\n \"a200\": #69f0ae,\n \"a400\": #00e676,\n \"a700\": #00c853\n);\n\n$clr-green: map-get($clr-green-list, \"base\");\n\n$clr-green-50: map-get($clr-green-list, \"50\");\n$clr-green-100: map-get($clr-green-list, \"100\");\n$clr-green-200: map-get($clr-green-list, \"200\");\n$clr-green-300: map-get($clr-green-list, \"300\");\n$clr-green-400: map-get($clr-green-list, \"400\");\n$clr-green-500: map-get($clr-green-list, \"500\");\n$clr-green-600: map-get($clr-green-list, \"600\");\n$clr-green-700: map-get($clr-green-list, \"700\");\n$clr-green-800: map-get($clr-green-list, \"800\");\n$clr-green-900: map-get($clr-green-list, \"900\");\n$clr-green-a100: map-get($clr-green-list, \"a100\");\n$clr-green-a200: map-get($clr-green-list, \"a200\");\n$clr-green-a400: map-get($clr-green-list, \"a400\");\n$clr-green-a700: map-get($clr-green-list, \"a700\");\n\n\n//\n// Light green\n//\n\n$clr-light-green-list: (\n \"base\": #8bc34a,\n \"50\": #f1f8e9,\n \"100\": #dcedc8,\n \"200\": #c5e1a5,\n \"300\": #aed581,\n \"400\": #9ccc65,\n \"500\": #8bc34a,\n \"600\": #7cb342,\n \"700\": #689f38,\n \"800\": #558b2f,\n \"900\": #33691e,\n \"a100\": #ccff90,\n \"a200\": #b2ff59,\n \"a400\": #76ff03,\n \"a700\": #64dd17\n);\n\n$clr-light-green: map-get($clr-light-green-list, \"base\");\n\n$clr-light-green-50: map-get($clr-light-green-list, \"50\");\n$clr-light-green-100: map-get($clr-light-green-list, \"100\");\n$clr-light-green-200: map-get($clr-light-green-list, \"200\");\n$clr-light-green-300: map-get($clr-light-green-list, \"300\");\n$clr-light-green-400: map-get($clr-light-green-list, \"400\");\n$clr-light-green-500: map-get($clr-light-green-list, \"500\");\n$clr-light-green-600: map-get($clr-light-green-list, \"600\");\n$clr-light-green-700: map-get($clr-light-green-list, \"700\");\n$clr-light-green-800: map-get($clr-light-green-list, \"800\");\n$clr-light-green-900: map-get($clr-light-green-list, \"900\");\n$clr-light-green-a100: map-get($clr-light-green-list, \"a100\");\n$clr-light-green-a200: map-get($clr-light-green-list, \"a200\");\n$clr-light-green-a400: map-get($clr-light-green-list, \"a400\");\n$clr-light-green-a700: map-get($clr-light-green-list, \"a700\");\n\n\n//\n// Lime\n//\n\n$clr-lime-list: (\n \"base\": #cddc39,\n \"50\": #f9fbe7,\n \"100\": #f0f4c3,\n \"200\": #e6ee9c,\n \"300\": #dce775,\n \"400\": #d4e157,\n \"500\": #cddc39,\n \"600\": #c0ca33,\n \"700\": #afb42b,\n \"800\": #9e9d24,\n \"900\": #827717,\n \"a100\": #f4ff81,\n \"a200\": #eeff41,\n \"a400\": #c6ff00,\n \"a700\": #aeea00\n);\n\n$clr-lime: map-get($clr-lime-list, \"base\");\n\n$clr-lime-50: map-get($clr-lime-list, \"50\");\n$clr-lime-100: map-get($clr-lime-list, \"100\");\n$clr-lime-200: map-get($clr-lime-list, \"200\");\n$clr-lime-300: map-get($clr-lime-list, \"300\");\n$clr-lime-400: map-get($clr-lime-list, \"400\");\n$clr-lime-500: map-get($clr-lime-list, \"500\");\n$clr-lime-600: map-get($clr-lime-list, \"600\");\n$clr-lime-700: map-get($clr-lime-list, \"700\");\n$clr-lime-800: map-get($clr-lime-list, \"800\");\n$clr-lime-900: map-get($clr-lime-list, \"900\");\n$clr-lime-a100: map-get($clr-lime-list, \"a100\");\n$clr-lime-a200: map-get($clr-lime-list, \"a200\");\n$clr-lime-a400: map-get($clr-lime-list, \"a400\");\n$clr-lime-a700: map-get($clr-lime-list, \"a700\");\n\n\n//\n// Yellow\n//\n\n$clr-yellow-list: (\n \"base\": #ffeb3b,\n \"50\": #fffde7,\n \"100\": #fff9c4,\n \"200\": #fff59d,\n \"300\": #fff176,\n \"400\": #ffee58,\n \"500\": #ffeb3b,\n \"600\": #fdd835,\n \"700\": #fbc02d,\n \"800\": #f9a825,\n \"900\": #f57f17,\n \"a100\": #ffff8d,\n \"a200\": #ffff00,\n \"a400\": #ffea00,\n \"a700\": #ffd600\n);\n\n$clr-yellow: map-get($clr-yellow-list, \"base\");\n\n$clr-yellow-50: map-get($clr-yellow-list, \"50\");\n$clr-yellow-100: map-get($clr-yellow-list, \"100\");\n$clr-yellow-200: map-get($clr-yellow-list, \"200\");\n$clr-yellow-300: map-get($clr-yellow-list, \"300\");\n$clr-yellow-400: map-get($clr-yellow-list, \"400\");\n$clr-yellow-500: map-get($clr-yellow-list, \"500\");\n$clr-yellow-600: map-get($clr-yellow-list, \"600\");\n$clr-yellow-700: map-get($clr-yellow-list, \"700\");\n$clr-yellow-800: map-get($clr-yellow-list, \"800\");\n$clr-yellow-900: map-get($clr-yellow-list, \"900\");\n$clr-yellow-a100: map-get($clr-yellow-list, \"a100\");\n$clr-yellow-a200: map-get($clr-yellow-list, \"a200\");\n$clr-yellow-a400: map-get($clr-yellow-list, \"a400\");\n$clr-yellow-a700: map-get($clr-yellow-list, \"a700\");\n\n\n//\n// amber\n//\n\n$clr-amber-list: (\n \"base\": #ffc107,\n \"50\": #fff8e1,\n \"100\": #ffecb3,\n \"200\": #ffe082,\n \"300\": #ffd54f,\n \"400\": #ffca28,\n \"500\": #ffc107,\n \"600\": #ffb300,\n \"700\": #ffa000,\n \"800\": #ff8f00,\n \"900\": #ff6f00,\n \"a100\": #ffe57f,\n \"a200\": #ffd740,\n \"a400\": #ffc400,\n \"a700\": #ffab00\n);\n\n$clr-amber: map-get($clr-amber-list, \"base\");\n\n$clr-amber-50: map-get($clr-amber-list, \"50\");\n$clr-amber-100: map-get($clr-amber-list, \"100\");\n$clr-amber-200: map-get($clr-amber-list, \"200\");\n$clr-amber-300: map-get($clr-amber-list, \"300\");\n$clr-amber-400: map-get($clr-amber-list, \"400\");\n$clr-amber-500: map-get($clr-amber-list, \"500\");\n$clr-amber-600: map-get($clr-amber-list, \"600\");\n$clr-amber-700: map-get($clr-amber-list, \"700\");\n$clr-amber-800: map-get($clr-amber-list, \"800\");\n$clr-amber-900: map-get($clr-amber-list, \"900\");\n$clr-amber-a100: map-get($clr-amber-list, \"a100\");\n$clr-amber-a200: map-get($clr-amber-list, \"a200\");\n$clr-amber-a400: map-get($clr-amber-list, \"a400\");\n$clr-amber-a700: map-get($clr-amber-list, \"a700\");\n\n\n//\n// Orange\n//\n\n$clr-orange-list: (\n \"base\": #ff9800,\n \"50\": #fff3e0,\n \"100\": #ffe0b2,\n \"200\": #ffcc80,\n \"300\": #ffb74d,\n \"400\": #ffa726,\n \"500\": #ff9800,\n \"600\": #fb8c00,\n \"700\": #f57c00,\n \"800\": #ef6c00,\n \"900\": #e65100,\n \"a100\": #ffd180,\n \"a200\": #ffab40,\n \"a400\": #ff9100,\n \"a700\": #ff6d00\n);\n\n$clr-orange: map-get($clr-orange-list, \"base\");\n\n$clr-orange-50: map-get($clr-orange-list, \"50\");\n$clr-orange-100: map-get($clr-orange-list, \"100\");\n$clr-orange-200: map-get($clr-orange-list, \"200\");\n$clr-orange-300: map-get($clr-orange-list, \"300\");\n$clr-orange-400: map-get($clr-orange-list, \"400\");\n$clr-orange-500: map-get($clr-orange-list, \"500\");\n$clr-orange-600: map-get($clr-orange-list, \"600\");\n$clr-orange-700: map-get($clr-orange-list, \"700\");\n$clr-orange-800: map-get($clr-orange-list, \"800\");\n$clr-orange-900: map-get($clr-orange-list, \"900\");\n$clr-orange-a100: map-get($clr-orange-list, \"a100\");\n$clr-orange-a200: map-get($clr-orange-list, \"a200\");\n$clr-orange-a400: map-get($clr-orange-list, \"a400\");\n$clr-orange-a700: map-get($clr-orange-list, \"a700\");\n\n\n//\n// Deep orange\n//\n\n$clr-deep-orange-list: (\n \"base\": #ff5722,\n \"50\": #fbe9e7,\n \"100\": #ffccbc,\n \"200\": #ffab91,\n \"300\": #ff8a65,\n \"400\": #ff7043,\n \"500\": #ff5722,\n \"600\": #f4511e,\n \"700\": #e64a19,\n \"800\": #d84315,\n \"900\": #bf360c,\n \"a100\": #ff9e80,\n \"a200\": #ff6e40,\n \"a400\": #ff3d00,\n \"a700\": #dd2c00\n);\n\n$clr-deep-orange: map-get($clr-deep-orange-list, \"base\");\n\n$clr-deep-orange-50: map-get($clr-deep-orange-list, \"50\");\n$clr-deep-orange-100: map-get($clr-deep-orange-list, \"100\");\n$clr-deep-orange-200: map-get($clr-deep-orange-list, \"200\");\n$clr-deep-orange-300: map-get($clr-deep-orange-list, \"300\");\n$clr-deep-orange-400: map-get($clr-deep-orange-list, \"400\");\n$clr-deep-orange-500: map-get($clr-deep-orange-list, \"500\");\n$clr-deep-orange-600: map-get($clr-deep-orange-list, \"600\");\n$clr-deep-orange-700: map-get($clr-deep-orange-list, \"700\");\n$clr-deep-orange-800: map-get($clr-deep-orange-list, \"800\");\n$clr-deep-orange-900: map-get($clr-deep-orange-list, \"900\");\n$clr-deep-orange-a100: map-get($clr-deep-orange-list, \"a100\");\n$clr-deep-orange-a200: map-get($clr-deep-orange-list, \"a200\");\n$clr-deep-orange-a400: map-get($clr-deep-orange-list, \"a400\");\n$clr-deep-orange-a700: map-get($clr-deep-orange-list, \"a700\");\n\n\n//\n// Brown\n//\n\n$clr-brown-list: (\n \"base\": #795548,\n \"50\": #efebe9,\n \"100\": #d7ccc8,\n \"200\": #bcaaa4,\n \"300\": #a1887f,\n \"400\": #8d6e63,\n \"500\": #795548,\n \"600\": #6d4c41,\n \"700\": #5d4037,\n \"800\": #4e342e,\n \"900\": #3e2723,\n);\n\n$clr-brown: map-get($clr-brown-list, \"base\");\n\n$clr-brown-50: map-get($clr-brown-list, \"50\");\n$clr-brown-100: map-get($clr-brown-list, \"100\");\n$clr-brown-200: map-get($clr-brown-list, \"200\");\n$clr-brown-300: map-get($clr-brown-list, \"300\");\n$clr-brown-400: map-get($clr-brown-list, \"400\");\n$clr-brown-500: map-get($clr-brown-list, \"500\");\n$clr-brown-600: map-get($clr-brown-list, \"600\");\n$clr-brown-700: map-get($clr-brown-list, \"700\");\n$clr-brown-800: map-get($clr-brown-list, \"800\");\n$clr-brown-900: map-get($clr-brown-list, \"900\");\n\n\n//\n// Grey\n//\n\n$clr-grey-list: (\n \"base\": #9e9e9e,\n \"50\": #fafafa,\n \"100\": #f5f5f5,\n \"200\": #eeeeee,\n \"300\": #e0e0e0,\n \"400\": #bdbdbd,\n \"500\": #9e9e9e,\n \"600\": #757575,\n \"700\": #616161,\n \"800\": #424242,\n \"900\": #212121,\n);\n\n$clr-grey: map-get($clr-grey-list, \"base\");\n\n$clr-grey-50: map-get($clr-grey-list, \"50\");\n$clr-grey-100: map-get($clr-grey-list, \"100\");\n$clr-grey-200: map-get($clr-grey-list, \"200\");\n$clr-grey-300: map-get($clr-grey-list, \"300\");\n$clr-grey-400: map-get($clr-grey-list, \"400\");\n$clr-grey-500: map-get($clr-grey-list, \"500\");\n$clr-grey-600: map-get($clr-grey-list, \"600\");\n$clr-grey-700: map-get($clr-grey-list, \"700\");\n$clr-grey-800: map-get($clr-grey-list, \"800\");\n$clr-grey-900: map-get($clr-grey-list, \"900\");\n\n\n//\n// Blue grey\n//\n\n$clr-blue-grey-list: (\n \"base\": #607d8b,\n \"50\": #eceff1,\n \"100\": #cfd8dc,\n \"200\": #b0bec5,\n \"300\": #90a4ae,\n \"400\": #78909c,\n \"500\": #607d8b,\n \"600\": #546e7a,\n \"700\": #455a64,\n \"800\": #37474f,\n \"900\": #263238,\n);\n\n$clr-blue-grey: map-get($clr-blue-grey-list, \"base\");\n\n$clr-blue-grey-50: map-get($clr-blue-grey-list, \"50\");\n$clr-blue-grey-100: map-get($clr-blue-grey-list, \"100\");\n$clr-blue-grey-200: map-get($clr-blue-grey-list, \"200\");\n$clr-blue-grey-300: map-get($clr-blue-grey-list, \"300\");\n$clr-blue-grey-400: map-get($clr-blue-grey-list, \"400\");\n$clr-blue-grey-500: map-get($clr-blue-grey-list, \"500\");\n$clr-blue-grey-600: map-get($clr-blue-grey-list, \"600\");\n$clr-blue-grey-700: map-get($clr-blue-grey-list, \"700\");\n$clr-blue-grey-800: map-get($clr-blue-grey-list, \"800\");\n$clr-blue-grey-900: map-get($clr-blue-grey-list, \"900\");\n\n\n//\n// Black\n//\n\n$clr-black-list: (\n \"base\": #000\n);\n\n$clr-black: map-get($clr-black-list, \"base\");\n\n\n//\n// White\n//\n\n$clr-white-list: (\n \"base\": #fff\n);\n\n$clr-white: map-get($clr-white-list, \"base\");\n\n\n//\n// List for all Colors for looping\n//\n\n$clr-list-all: (\n \"red\": $clr-red-list,\n \"pink\": $clr-pink-list,\n \"purple\": $clr-purple-list,\n \"deep-purple\": $clr-deep-purple-list,\n \"indigo\": $clr-indigo-list,\n \"blue\": $clr-blue-list,\n \"light-blue\": $clr-light-blue-list,\n \"cyan\": $clr-cyan-list,\n \"teal\": $clr-teal-list,\n \"green\": $clr-green-list,\n \"light-green\": $clr-light-green-list,\n \"lime\": $clr-lime-list,\n \"yellow\": $clr-yellow-list,\n \"amber\": $clr-amber-list,\n \"orange\": $clr-orange-list,\n \"deep-orange\": $clr-deep-orange-list,\n \"brown\": $clr-brown-list,\n \"grey\": $clr-grey-list,\n \"blue-grey\": $clr-blue-grey-list,\n \"black\": $clr-black-list,\n \"white\": $clr-white-list\n);\n\n\n//\n// Typography\n//\n\n$clr-ui-display-4: $clr-grey-600;\n$clr-ui-display-3: $clr-grey-600;\n$clr-ui-display-2: $clr-grey-600;\n$clr-ui-display-1: $clr-grey-600;\n$clr-ui-headline: $clr-grey-900;\n$clr-ui-title: $clr-grey-900;\n$clr-ui-subhead-1: $clr-grey-900;\n$clr-ui-body-2: $clr-grey-900;\n$clr-ui-body-1: $clr-grey-900;\n$clr-ui-caption: $clr-grey-600;\n$clr-ui-menu: $clr-grey-900;\n$clr-ui-button: $clr-grey-900;\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-footnotes-icon: svg-load(\"@mdi/svg/svg/keyboard-return.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Footnote reference\n [id^=\"fnref:\"]:target {\n scroll-margin-top: initial;\n margin-top: -1 * px2rem(48px + 24px - 4px);\n padding-top: px2rem(48px + 24px - 4px);\n }\n\n // Footnote\n [id^=\"fn:\"]:target {\n scroll-margin-top: initial;\n margin-top: -1 * px2rem(48px + 24px - 3px);\n padding-top: px2rem(48px + 24px - 3px);\n }\n\n // Footnote container\n .footnote {\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n\n // Footnote list - omit left indentation\n ol {\n margin-left: 0;\n }\n\n // Footnote list item\n li {\n transition: color 125ms;\n\n // Darken color on target\n &:target {\n color: var(--md-default-fg-color);\n }\n\n // Show backreferences on footnote hover\n &:hover .footnote-backref,\n &:target .footnote-backref {\n transform: translateX(0);\n opacity: 1;\n }\n\n // Adjust spacing on first child\n > :first-child {\n margin-top: 0;\n }\n }\n }\n\n // Footnote backreference\n .footnote-backref {\n display: inline-block;\n color: var(--md-typeset-a-color);\n // Hack: omit Unicode arrow for replacement with icon\n font-size: 0;\n vertical-align: text-bottom;\n transform: translateX(px2rem(5px));\n opacity: 0;\n transition:\n color 250ms,\n transform 250ms 250ms,\n opacity 125ms 250ms;\n\n // [print]: Show footnote backreferences\n @media print {\n color: var(--md-typeset-a-color);\n transform: translateX(0);\n opacity: 1;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-5px));\n }\n\n // Adjust color on hover\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Footnote backreference icon\n &::before {\n display: inline-block;\n width: px2rem(16px);\n height: px2rem(16px);\n background-color: currentColor;\n mask-image: var(--md-footnotes-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1)\n }\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Headerlink\n .headerlink {\n display: inline-block;\n margin-left: px2rem(10px);\n color: var(--md-default-fg-color--lighter);\n opacity: 0;\n transition:\n color 250ms,\n opacity 125ms;\n\n // [print]: Hide headerlinks\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(10px);\n margin-left: initial;\n }\n }\n\n // Show headerlinks on parent hover\n :hover > .headerlink,\n :target > .headerlink,\n .headerlink:focus {\n opacity: 1;\n transition:\n color 250ms,\n opacity 125ms;\n }\n\n // Adjust color on parent target or focus/hover\n :target > .headerlink,\n .headerlink:focus,\n .headerlink:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Adjust scroll offset for all elements with `id` attributes - general scroll\n // margin offset for anything that can be targeted. Browser support is pretty\n // decent by now, but Edge <79 and Safari (iOS and macOS) still don't support\n // it properly, so we settle with a cross-browser anchor correction solution.\n :target {\n scroll-margin-top: px2rem(48px + 24px);\n }\n\n // Adjust scroll offset for headlines of level 1-3\n h1:target,\n h2:target,\n h3:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px - 4px);\n padding-top: px2rem(48px + 24px - 4px);\n content: \"\";\n }\n }\n\n // Adjust scroll offset for headlines of level 4\n h4:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px - 3px);\n padding-top: px2rem(48px + 24px - 3px);\n content: \"\";\n }\n }\n\n // Adjust scroll offset for headlines of level 5-6\n h5:target,\n h6:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px);\n padding-top: px2rem(48px + 24px);\n content: \"\";\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Arithmatex container\n div.arithmatex {\n overflow: auto;\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n margin: 0 px2rem(-16px);\n }\n\n // Arithmatex content\n > * {\n width: min-content;\n margin: 1em auto !important;\n padding: 0 px2rem(16px);\n touch-action: auto;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Deletions, additions and comments\n del.critic,\n ins.critic,\n .critic.comment {\n box-decoration-break: clone;\n }\n\n // Deletion\n del.critic {\n background-color: var(--md-typeset-del-color);\n }\n\n // Addition\n ins.critic {\n background-color: var(--md-typeset-ins-color);\n }\n\n // Comment\n .critic.comment {\n color: var(--md-code-hl-comment-color);\n\n // Comment opening mark\n &::before {\n content: \"/* \";\n }\n\n // Comment closing mark\n &::after {\n content: \" */\";\n }\n }\n\n // Critic block\n .critic.block {\n display: block;\n margin: 1em 0;\n padding-right: px2rem(16px);\n padding-left: px2rem(16px);\n overflow: auto;\n box-shadow: none;\n\n // Adjust spacing on first child\n > :first-child {\n margin-top: 0.5em;\n }\n\n // Adjust spacing on last child\n > :last-child {\n margin-bottom: 0.5em;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-details-icon: svg-load(\"@mdi/svg/svg/chevron-right.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Details\n details {\n @extend .admonition;\n\n display: block;\n padding-top: 0;\n overflow: visible;\n\n // Details title icon - rotate icon on transition to open state\n &[open] > summary::after {\n transform: rotate(90deg);\n }\n\n // Adjust spacing for details in closed state\n &:not([open]) {\n padding-bottom: 0;\n box-shadow: none;\n\n // Hack: we cannot set `overflow: hidden` on the `details` element (which\n // is why we set it to `overflow: visible`, as the outline would not be\n // visible when focusing. Therefore, we must set the border radius on the\n // summary explicitly.\n > summary {\n border-radius: px2rem(2px);\n }\n }\n\n // Hack: omit margin collapse\n &::after {\n display: table;\n content: \"\";\n }\n }\n\n // Details title\n summary {\n @extend .admonition-title;\n\n display: block;\n min-height: px2rem(20px);\n padding: px2rem(8px) px2rem(36px) px2rem(8px) px2rem(40px);\n border-top-left-radius: px2rem(2px);\n border-top-right-radius: px2rem(2px);\n cursor: pointer;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding: px2rem(8px) px2rem(44px) px2rem(8px) px2rem(36px);\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n\n // Details marker\n &::after {\n position: absolute;\n top: px2rem(8px);\n right: px2rem(8px);\n width: px2rem(20px);\n height: px2rem(20px);\n background-color: currentColor;\n mask-image: var(--md-details-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n transform: rotate(0deg);\n transition: transform 250ms;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(8px);\n transform: rotate(180deg);\n }\n }\n\n // Hide native details marker\n &::-webkit-details-marker {\n display: none;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Emoji and icon container\n .emojione,\n .twemoji,\n .gemoji {\n display: inline-block;\n height: px2em(18px);\n vertical-align: text-top;\n\n // Icon - inlined via mkdocs-material-extensions\n svg {\n width: px2em(18px);\n max-height: 100%;\n fill: currentColor;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: syntax highlighting\n// ----------------------------------------------------------------------------\n\n// Code block\n.highlight {\n\n .o, // Operator\n .ow { // Operator, word\n color: var(--md-code-hl-operator-color);\n }\n\n .p { // Punctuation\n color: var(--md-code-hl-punctuation-color);\n }\n\n .cpf, // Comment, preprocessor file\n .l, // Literal\n .s, // Literal, string\n .sb, // Literal, string backticks\n .sc, // Literal, string char\n .s2, // Literal, string double\n .si, // Literal, string interpol\n .s1, // Literal, string single\n .ss { // Literal, string symbol\n color: var(--md-code-hl-string-color);\n }\n\n .cp, // Comment, pre-processor\n .se, // Literal, string escape\n .sh, // Literal, string heredoc\n .sr, // Literal, string regex\n .sx { // Literal, string other\n color: var(--md-code-hl-special-color);\n }\n\n .m, // Number\n .mf, // Number, float\n .mh, // Number, hex\n .mi, // Number, integer\n .il, // Number, integer long\n .mo { // Number, octal\n color: var(--md-code-hl-number-color);\n }\n\n .k, // Keyword,\n .kd, // Keyword, declaration\n .kn, // Keyword, namespace\n .kp, // Keyword, pseudo\n .kr, // Keyword, reserved\n .kt { // Keyword, type\n color: var(--md-code-hl-keyword-color);\n }\n\n .kc, // Keyword, constant\n .n { // Name\n color: var(--md-code-hl-name-color);\n }\n\n .no, // Name, constant\n .nb, // Name, builtin\n .bp { // Name, builtin pseudo\n color: var(--md-code-hl-constant-color);\n }\n\n .nc, // Name, class\n .ne, // Name, exception\n .nf, // Name, function\n .nn { // Name, namespace\n color: var(--md-code-hl-function-color);\n }\n\n .nd, // Name, decorator\n .ni, // Name, entity\n .nl, // Name, label\n .nt { // Name, tag\n color: var(--md-code-hl-keyword-color);\n }\n\n .c, // Comment\n .cm, // Comment, multiline\n .c1, // Comment, single\n .ch, // Comment, shebang\n .cs, // Comment, special\n .sd { // Literal, string doc\n color: var(--md-code-hl-comment-color);\n }\n\n .na, // Name, attribute\n .nv, // Variable,\n .vc, // Variable, class\n .vg, // Variable, global\n .vi { // Variable, instance\n color: var(--md-code-hl-variable-color);\n }\n\n .ge, // Generic, emph\n .gr, // Generic, error\n .gh, // Generic, heading\n .go, // Generic, output\n .gp, // Generic, prompt\n .gs, // Generic, strong\n .gu, // Generic, subheading\n .gt { // Generic, traceback\n color: var(--md-code-hl-generic-color);\n }\n\n .gd, // Diff, delete\n .gi { // Diff, insert\n margin: 0 px2em(-2px);\n padding: 0 px2em(2px);\n border-radius: px2rem(2px);\n }\n\n .gd { // Diff, delete\n background-color: var(--md-typeset-del-color);\n }\n\n .gi { // Diff, insert\n background-color: var(--md-typeset-ins-color)\n }\n\n // Highlighted line\n .hll {\n display: block;\n margin: 0 px2em(-16px, 13.6px);\n padding: 0 px2em(16px, 13.6px);\n background-color: var(--md-code-hl-color)\n }\n\n // Code block line numbers (inline)\n [data-linenos]::before {\n position: sticky;\n left: px2em(-16px, 13.6px);\n float: left;\n margin-right: px2em(16px, 13.6px);\n margin-left: px2em(-16px, 13.6px);\n padding-left: px2em(16px, 13.6px);\n color: var(--md-default-fg-color--light);\n background-color: var(--md-code-bg-color);\n box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset;\n content: attr(data-linenos);\n user-select: none;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: layout\n// ----------------------------------------------------------------------------\n\n// Code block with line numbers\n.highlighttable {\n display: flow-root;\n overflow: hidden;\n\n // Set table elements to block layout, because otherwise the whole flexbox\n // hacking won't work correctly\n tbody,\n td {\n display: block;\n padding: 0;\n }\n\n // We need to use flexbox layout, because otherwise it's not possible to\n // make the code container scroll while keeping the line numbers static\n tr {\n display: flex;\n }\n\n // The pre tags are nested inside a table, so we need to omit the margin\n // because it collapses below all the overflows\n pre {\n margin: 0;\n }\n\n // Code block line numbers - disable user selection, so code can be easily\n // copied without accidentally also copying the line numbers\n .linenos {\n padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px);\n padding-right: 0;\n font-size: px2em(13.6px);\n background-color: var(--md-code-bg-color);\n user-select: none;\n }\n\n // Code block line numbers container\n .linenodiv {\n padding-right: px2em(8px, 13.6px);\n box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset;\n\n // Adjust colors and alignment\n pre {\n color: var(--md-default-fg-color--light);\n text-align: right;\n }\n }\n\n // Code block container - stretch to remaining space\n .code {\n flex: 1;\n overflow: hidden;\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Code block with line numbers\n .highlighttable {\n margin: 1em 0;\n direction: ltr;\n border-radius: px2rem(2px);\n\n // Omit rounded borders on contained code block\n code {\n border-radius: 0;\n }\n }\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n\n // Top-level code block\n > .highlight {\n margin: 1em px2rem(-16px);\n\n // Highlighted line\n .hll {\n margin: 0 px2rem(-16px);\n padding: 0 px2rem(16px);\n }\n\n // Omit rounded borders\n code {\n border-radius: 0;\n }\n }\n\n // Top-level code block with line numbers\n > .highlighttable {\n margin: 1em px2rem(-16px);\n border-radius: 0;\n\n // Highlighted line\n .hll {\n margin: 0 px2rem(-16px);\n padding: 0 px2rem(16px);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Keyboard key\n .keys {\n\n // Keyboard key icon\n kbd::before,\n kbd::after {\n position: relative;\n margin: 0;\n color: inherit;\n -moz-osx-font-smoothing: initial;\n -webkit-font-smoothing: initial;\n }\n\n // Surrounding text\n span {\n padding: 0 px2em(3.2px);\n color: var(--md-default-fg-color--light);\n }\n\n // Define keyboard keys with left icon\n @each $name, $code in (\n\n // Modifiers\n \"alt\": \"\\2387\",\n \"left-alt\": \"\\2387\",\n \"right-alt\": \"\\2387\",\n \"command\": \"\\2318\",\n \"left-command\": \"\\2318\",\n \"right-command\": \"\\2318\",\n \"control\": \"\\2303\",\n \"left-control\": \"\\2303\",\n \"right-control\": \"\\2303\",\n \"meta\": \"\\25C6\",\n \"left-meta\": \"\\25C6\",\n \"right-meta\": \"\\25C6\",\n \"option\": \"\\2325\",\n \"left-option\": \"\\2325\",\n \"right-option\": \"\\2325\",\n \"shift\": \"\\21E7\",\n \"left-shift\": \"\\21E7\",\n \"right-shift\": \"\\21E7\",\n \"super\": \"\\2756\",\n \"left-super\": \"\\2756\",\n \"right-super\": \"\\2756\",\n \"windows\": \"\\229E\",\n \"left-windows\": \"\\229E\",\n \"right-windows\": \"\\229E\",\n\n // Other keys\n \"arrow-down\": \"\\2193\",\n \"arrow-left\": \"\\2190\",\n \"arrow-right\": \"\\2192\",\n \"arrow-up\": \"\\2191\",\n \"backspace\": \"\\232B\",\n \"backtab\": \"\\21E4\",\n \"caps-lock\": \"\\21EA\",\n \"clear\": \"\\2327\",\n \"context-menu\": \"\\2630\",\n \"delete\": \"\\2326\",\n \"eject\": \"\\23CF\",\n \"end\": \"\\2913\",\n \"escape\": \"\\238B\",\n \"home\": \"\\2912\",\n \"insert\": \"\\2380\",\n \"page-down\": \"\\21DF\",\n \"page-up\": \"\\21DE\",\n \"print-screen\": \"\\2399\"\n ) {\n .key-#{$name} {\n &::before {\n padding-right: px2em(6.4px);\n content: $code;\n }\n }\n }\n\n // Define keyboard keys with right icon\n @each $name, $code in (\n \"tab\": \"\\21E5\",\n \"num-enter\": \"\\2324\",\n \"enter\": \"\\23CE\"\n ) {\n .key-#{$name} {\n &::after {\n padding-left: px2em(6.4px);\n content: $code;\n }\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Tabbed block content\n .tabbed-content {\n display: none;\n order: 99;\n width: 100%;\n box-shadow: 0 px2rem(-1px) var(--md-default-fg-color--lightest);\n\n // [print]: Show all tabs (even hidden ones) when printing\n @media print {\n display: block;\n order: initial;\n }\n\n // Code block is the only child of a tab - remove margin and mirror\n // previous (now deprecated) SuperFences code block grouping behavior\n > pre:only-child,\n > .highlight:only-child pre,\n > .highlighttable:only-child {\n margin: 0;\n\n // Omit rounded borders\n > code {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n }\n\n // Adjust spacing for nested tab\n > .tabbed-set {\n margin: 0;\n }\n }\n\n // Tabbed block container\n .tabbed-set {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n margin: 1em 0;\n border-radius: px2rem(2px);\n\n // Tab radio button - the Tabbed extension will generate radio buttons with\n // labels, so tabs can be triggered without the necessity for JavaScript.\n // This is pretty cool, as it has great accessibility out-of-the box, so\n // we just hide the radio button and toggle the label color for indication.\n > input {\n position: absolute;\n width: 0;\n height: 0;\n opacity: 0;\n\n // Tab label for checked radio button\n &:checked + label {\n color: var(--md-accent-fg-color);\n border-color: var(--md-accent-fg-color);\n\n // Show tabbed block content\n & + .tabbed-content {\n display: block;\n }\n }\n\n // Tab label on focus\n &:focus + label {\n outline-style: auto;\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) + label {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n // Tab label\n > label {\n z-index: 1;\n width: auto;\n padding: px2em(12px, 12.8px) 1.25em px2em(10px, 12.8px);\n color: var(--md-default-fg-color--light);\n font-weight: 700;\n font-size: px2rem(12.8px);\n border-bottom: px2rem(2px) solid transparent;\n cursor: pointer;\n transition: color 250ms;\n\n // Tab label on hover\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-tasklist-icon: svg-load(\n \"@primer/octicons/build/svg/check-circle-fill-24.svg\"\n );\n --md-tasklist-icon--checked: svg-load(\n \"@primer/octicons/build/svg/check-circle-fill-24.svg\"\n );\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Tasklist item\n .task-list-item {\n position: relative;\n list-style-type: none;\n\n // Make checkbox items align with normal list items, but position\n // everything in ems for correct layout at smaller font sizes\n [type=\"checkbox\"] {\n position: absolute;\n top: 0.45em;\n left: -2em;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: -2em;\n left: initial;\n }\n }\n }\n\n // Hide native checkbox, when custom classes are enabled\n .task-list-control [type=\"checkbox\"] {\n z-index: -1;\n opacity: 0;\n }\n\n // Tasklist indicator in unchecked state\n .task-list-indicator::before {\n position: absolute;\n top: 0.15em;\n left: px2em(-24px);\n width: px2em(20px);\n height: px2em(20px);\n background-color: var(--md-default-fg-color--lightest);\n mask-image: var(--md-tasklist-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2em(-24px);\n left: initial;\n }\n }\n\n // Tasklist indicator in checked state\n [type=\"checkbox\"]:checked + .task-list-indicator::before {\n background-color: $clr-green-a400;\n mask-image: var(--md-tasklist-icon--checked);\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/assets/stylesheets/palette.39b8e14a.min.css b/docs/assets/stylesheets/palette.39b8e14a.min.css deleted file mode 100644 index 41336cd..0000000 --- a/docs/assets/stylesheets/palette.39b8e14a.min.css +++ /dev/null @@ -1,3 +0,0 @@ -[data-md-color-accent=red]{--md-accent-fg-color: hsla(348, 100%, 55%, 1);--md-accent-fg-color--transparent: hsla(348, 100%, 55%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=pink]{--md-accent-fg-color: hsla(339, 100%, 48%, 1);--md-accent-fg-color--transparent: hsla(339, 100%, 48%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=purple]{--md-accent-fg-color: hsla(291, 96%, 62%, 1);--md-accent-fg-color--transparent: hsla(291, 96%, 62%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=deep-purple]{--md-accent-fg-color: hsla(256, 100%, 65%, 1);--md-accent-fg-color--transparent: hsla(256, 100%, 65%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=indigo]{--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=blue]{--md-accent-fg-color: hsla(218, 100%, 63%, 1);--md-accent-fg-color--transparent: hsla(218, 100%, 63%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=light-blue]{--md-accent-fg-color: hsla(203, 100%, 46%, 1);--md-accent-fg-color--transparent: hsla(203, 100%, 46%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=cyan]{--md-accent-fg-color: hsla(188, 100%, 42%, 1);--md-accent-fg-color--transparent: hsla(188, 100%, 42%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=teal]{--md-accent-fg-color: hsla(172, 100%, 37%, 1);--md-accent-fg-color--transparent: hsla(172, 100%, 37%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=green]{--md-accent-fg-color: hsla(145, 100%, 39%, 1);--md-accent-fg-color--transparent: hsla(145, 100%, 39%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=light-green]{--md-accent-fg-color: hsla(97, 81%, 48%, 1);--md-accent-fg-color--transparent: hsla(97, 81%, 48%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=lime]{--md-accent-fg-color: hsla(75, 100%, 46%, 1);--md-accent-fg-color--transparent: hsla(75, 100%, 46%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=yellow]{--md-accent-fg-color: hsla(50, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(50, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=amber]{--md-accent-fg-color: hsla(40, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(40, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=orange]{--md-accent-fg-color: hsla(34, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(34, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=deep-orange]{--md-accent-fg-color: hsla(14, 100%, 63%, 1);--md-accent-fg-color--transparent: hsla(14, 100%, 63%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=red]{--md-primary-fg-color: hsla(1, 83%, 63%, 1);--md-primary-fg-color--light: hsla(0, 69%, 67%, 1);--md-primary-fg-color--dark: hsla(1, 77%, 55%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=pink]{--md-primary-fg-color: hsla(340, 82%, 52%, 1);--md-primary-fg-color--light: hsla(340, 82%, 59%, 1);--md-primary-fg-color--dark: hsla(336, 78%, 43%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=purple]{--md-primary-fg-color: hsla(291, 47%, 51%, 1);--md-primary-fg-color--light: hsla(291, 47%, 60%, 1);--md-primary-fg-color--dark: hsla(287, 65%, 40%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=deep-purple]{--md-primary-fg-color: hsla(262, 47%, 55%, 1);--md-primary-fg-color--light: hsla(262, 47%, 63%, 1);--md-primary-fg-color--dark: hsla(262, 52%, 47%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=indigo]{--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=blue]{--md-primary-fg-color: hsla(207, 90%, 54%, 1);--md-primary-fg-color--light: hsla(207, 90%, 61%, 1);--md-primary-fg-color--dark: hsla(210, 79%, 46%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=light-blue]{--md-primary-fg-color: hsla(199, 98%, 48%, 1);--md-primary-fg-color--light: hsla(199, 92%, 56%, 1);--md-primary-fg-color--dark: hsla(201, 98%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=cyan]{--md-primary-fg-color: hsla(187, 100%, 42%, 1);--md-primary-fg-color--light: hsla(187, 71%, 50%, 1);--md-primary-fg-color--dark: hsla(186, 100%, 33%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=teal]{--md-primary-fg-color: hsla(174, 100%, 29%, 1);--md-primary-fg-color--light: hsla(174, 63%, 40%, 1);--md-primary-fg-color--dark: hsla(173, 100%, 24%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=green]{--md-primary-fg-color: hsla(122, 39%, 49%, 1);--md-primary-fg-color--light: hsla(123, 38%, 57%, 1);--md-primary-fg-color--dark: hsla(123, 43%, 39%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=light-green]{--md-primary-fg-color: hsla(88, 50%, 53%, 1);--md-primary-fg-color--light: hsla(88, 50%, 60%, 1);--md-primary-fg-color--dark: hsla(92, 48%, 42%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=lime]{--md-primary-fg-color: hsla(66, 70%, 54%, 1);--md-primary-fg-color--light: hsla(66, 70%, 61%, 1);--md-primary-fg-color--dark: hsla(62, 61%, 44%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=yellow]{--md-primary-fg-color: hsla(54, 100%, 62%, 1);--md-primary-fg-color--light: hsla(54, 100%, 67%, 1);--md-primary-fg-color--dark: hsla(43, 96%, 58%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=amber]{--md-primary-fg-color: hsla(45, 100%, 51%, 1);--md-primary-fg-color--light: hsla(45, 100%, 58%, 1);--md-primary-fg-color--dark: hsla(38, 100%, 50%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=orange]{--md-primary-fg-color: hsla(36, 100%, 57%, 1);--md-primary-fg-color--light: hsla(36, 100%, 57%, 1);--md-primary-fg-color--dark: hsla(33, 100%, 49%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=deep-orange]{--md-primary-fg-color: hsla(14, 100%, 63%, 1);--md-primary-fg-color--light: hsla(14, 100%, 70%, 1);--md-primary-fg-color--dark: hsla(14, 91%, 54%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=brown]{--md-primary-fg-color: hsla(16, 25%, 38%, 1);--md-primary-fg-color--light: hsla(16, 18%, 47%, 1);--md-primary-fg-color--dark: hsla(14, 26%, 29%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=grey]{--md-primary-fg-color: hsla(0, 0%, 46%, 1);--md-primary-fg-color--light: hsla(0, 0%, 62%, 1);--md-primary-fg-color--dark: hsla(0, 0%, 38%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=blue-grey]{--md-primary-fg-color: hsla(199, 18%, 40%, 1);--md-primary-fg-color--light: hsla(200, 18%, 46%, 1);--md-primary-fg-color--dark: hsla(199, 18%, 33%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=white]{--md-primary-fg-color: hsla(0, 0%, 100%, 1);--md-primary-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-primary-fg-color--dark: hsla(0, 0%, 0%, 0.07);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);--md-typeset-a-color: hsla(231, 48%, 48%, 1)}@media screen and (min-width: 60em){[data-md-color-primary=white] .md-search__input{background-color:rgba(0,0,0,.07)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-moz-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input:hover{background-color:rgba(0,0,0,.32)}}@media screen and (min-width: 76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid rgba(0,0,0,.07)}}[data-md-color-primary=black]{--md-primary-fg-color: hsla(0, 0%, 0%, 1);--md-primary-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-primary-fg-color--dark: hsla(0, 0%, 0%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-typeset-a-color: hsla(231, 48%, 48%, 1)}[data-md-color-primary=black] .md-header{background-color:#000}@media screen and (max-width: 59.9375em){[data-md-color-primary=black] .md-nav__source{background-color:rgba(0,0,0,.87)}}@media screen and (min-width: 60em){[data-md-color-primary=black] .md-search__input{background-color:rgba(255,255,255,.12)}[data-md-color-primary=black] .md-search__input:hover{background-color:rgba(255,255,255,.3)}}@media screen and (max-width: 76.1875em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:#000}}@media screen and (min-width: 76.25em){[data-md-color-primary=black] .md-tabs{background-color:#000}}@media screen{[data-md-color-scheme=slate]{--md-hue: 232;--md-default-fg-color: hsla(var(--md-hue), 75%, 95%, 1);--md-default-fg-color--light: hsla(var(--md-hue), 75%, 90%, 0.62);--md-default-fg-color--lighter: hsla(var(--md-hue), 75%, 90%, 0.32);--md-default-fg-color--lightest: hsla(var(--md-hue), 75%, 90%, 0.12);--md-default-bg-color: hsla(var(--md-hue), 15%, 21%, 1);--md-default-bg-color--light: hsla(var(--md-hue), 15%, 21%, 0.54);--md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 21%, 0.26);--md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 21%, 0.07);--md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1);--md-code-bg-color: hsla(var(--md-hue), 15%, 15%, 1);--md-code-hl-color: hsla(218, 100%, 63%, 0.15);--md-code-hl-number-color: hsla(6, 74%, 63%, 1);--md-code-hl-special-color: hsla(340, 83%, 66%, 1);--md-code-hl-function-color: hsla(291, 57%, 65%, 1);--md-code-hl-constant-color: hsla(250, 62%, 70%, 1);--md-code-hl-keyword-color: hsla(219, 66%, 64%, 1);--md-code-hl-string-color: hsla(150, 58%, 44%, 1);--md-typeset-a-color: var(--md-primary-fg-color--light);--md-typeset-mark-color: hsla(218, 100%, 63%, 0.3);--md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12);--md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2);--md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1);--md-admonition-bg-color: hsla(var(--md-hue), 0%, 100%, 0.025);--md-footer-bg-color: hsla(var(--md-hue), 15%, 12%, 0.87);--md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 10%, 1)}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color: hsla(231, 44%, 56%, 1)}} - -/*# sourceMappingURL=palette.39b8e14a.min.css.map*/ \ No newline at end of file diff --git a/docs/assets/stylesheets/palette.39b8e14a.min.css.map b/docs/assets/stylesheets/palette.39b8e14a.min.css.map deleted file mode 100644 index 1036b17..0000000 --- a/docs/assets/stylesheets/palette.39b8e14a.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/assets/stylesheets/palette/_accent.scss","webpack:///./src/assets/stylesheets/palette/_primary.scss","webpack:///./src/assets/stylesheets/utilities/_break.scss","webpack:///./src/assets/stylesheets/palette/_scheme.scss"],"names":[],"mappings":"AA8CE,2BACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,8BACE,6CACA,4DAOE,2CACA,oDAVJ,mCACE,8CACA,6DAOE,2CACA,oDAVJ,8BACE,6CACA,4DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,kCACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,6BACE,8CACA,6DAOE,2CACA,oDAVJ,mCACE,4CACA,2DAOE,2CACA,oDAVJ,4BACE,6CACA,4DAIE,4CACA,mDAPJ,8BACE,6CACA,4DAIE,4CACA,mDAPJ,6BACE,6CACA,4DAIE,4CACA,mDAPJ,8BACE,6CACA,4DAIE,4CACA,mDAPJ,mCACE,6CACA,4DAOE,2CACA,oDCPJ,4BACE,4CACA,mDACA,kDAOE,4CACA,qDAXJ,6BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,+BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,oCACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,+BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,6BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,mCACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,6BACE,+CACA,qDACA,qDAOE,4CACA,qDAXJ,6BACE,+CACA,qDACA,qDAOE,4CACA,qDAXJ,8BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,oCACE,6CACA,oDACA,mDAOE,4CACA,qDAXJ,6BACE,6CACA,oDACA,mDAIE,6CACA,oDARJ,+BACE,8CACA,qDACA,mDAIE,6CACA,oDARJ,8BACE,8CACA,qDACA,oDAIE,6CACA,oDARJ,+BACE,8CACA,qDACA,oDAIE,6CACA,oDARJ,oCACE,8CACA,qDACA,mDAOE,4CACA,qDAXJ,8BACE,6CACA,oDACA,mDAOE,4CACA,qDAXJ,6BACE,2CACA,kDACA,iDAOE,4CACA,qDAXJ,kCACE,8CACA,qDACA,oDAOE,4CACA,qDAUN,8BACE,4CACA,qDACA,mDACA,6CACA,oDAGA,6CC6GE,oCDvGA,gDACE,iCAGA,iEACE,sBAIF,2EACE,sBADF,kEACE,sBADF,uEACE,sBADF,6DACE,sBAIF,sDACE,kCCwFJ,uCD/EA,uCACE,4CAUN,8BACE,0CACA,oDACA,gDACA,4CACA,qDAGA,6CAGA,yCACE,sBC0EA,yCDnEA,8CACE,kCCgDF,oCDxCA,gDACE,uCAGA,sDACE,uCCqDJ,yCD5CA,iFACE,uBCyBF,uCDjBA,uCACE,uBEhJN,cAGE,6BAKE,cAGA,wDACA,kEACA,oEACA,qEACA,wDACA,kEACA,oEACA,qEAGA,qDACA,qDAGA,+CACA,gDACA,mDACA,oDACA,oDACA,mDACA,kDAGA,wDAGA,mDAGA,4DACA,kEACA,gEAGA,+DAGA,0DACA,6DAGA,oHAIE,8C","file":"assets/stylesheets/palette.39b8e14a.min.css","sourcesContent":["////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n@each $name, $color in (\n \"red\": $clr-red-a400,\n \"pink\": $clr-pink-a400,\n \"purple\": $clr-purple-a200,\n \"deep-purple\": $clr-deep-purple-a200,\n \"indigo\": $clr-indigo-a200,\n \"blue\": $clr-blue-a200,\n \"light-blue\": $clr-light-blue-a700,\n \"cyan\": $clr-cyan-a700,\n \"teal\": $clr-teal-a700,\n \"green\": $clr-green-a700,\n \"light-green\": $clr-light-green-a700,\n \"lime\": $clr-lime-a700,\n \"yellow\": $clr-yellow-a700,\n \"amber\": $clr-amber-a700,\n \"orange\": $clr-orange-a400,\n \"deep-orange\": $clr-deep-orange-a200\n) {\n\n // Color palette\n [data-md-color-accent=\"#{$name}\"] {\n --md-accent-fg-color: hsla(#{hex2hsl($color)}, 1);\n --md-accent-fg-color--transparent: hsla(#{hex2hsl($color)}, 0.1);\n\n // Inverted text for lighter shades\n @if index(\"lime\" \"yellow\" \"amber\" \"orange\", $name) {\n --md-accent-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54);\n } @else {\n --md-accent-bg-color: hsla(0, 0%, 100%, 1);\n --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n@each $name, $colors in (\n \"red\": $clr-red-400 $clr-red-300 $clr-red-600,\n \"pink\": $clr-pink-500 $clr-pink-400 $clr-pink-700,\n \"purple\": $clr-purple-400 $clr-purple-300 $clr-purple-600,\n \"deep-purple\": $clr-deep-purple-400 $clr-deep-purple-300 $clr-deep-purple-500,\n \"indigo\": $clr-indigo-500 $clr-indigo-400 $clr-indigo-700,\n \"blue\": $clr-blue-500 $clr-blue-400 $clr-blue-700,\n \"light-blue\": $clr-light-blue-500 $clr-light-blue-400 $clr-light-blue-700,\n \"cyan\": $clr-cyan-500 $clr-cyan-400 $clr-cyan-700,\n \"teal\": $clr-teal-500 $clr-teal-400 $clr-teal-700,\n \"green\": $clr-green-500 $clr-green-400 $clr-green-700,\n \"light-green\": $clr-light-green-500 $clr-light-green-400 $clr-light-green-700,\n \"lime\": $clr-lime-500 $clr-lime-400 $clr-lime-700,\n \"yellow\": $clr-yellow-500 $clr-yellow-400 $clr-yellow-700,\n \"amber\": $clr-amber-500 $clr-amber-400 $clr-amber-700,\n \"orange\": $clr-orange-400 $clr-orange-400 $clr-orange-600,\n \"deep-orange\": $clr-deep-orange-400 $clr-deep-orange-300 $clr-deep-orange-600,\n \"brown\": $clr-brown-500 $clr-brown-400 $clr-brown-700,\n \"grey\": $clr-grey-600 $clr-grey-500 $clr-grey-700,\n \"blue-grey\": $clr-blue-grey-600 $clr-blue-grey-500 $clr-blue-grey-700\n) {\n\n // Color palette\n [data-md-color-primary=\"#{$name}\"] {\n --md-primary-fg-color: hsla(#{hex2hsl(nth($colors, 1))}, 1);\n --md-primary-fg-color--light: hsla(#{hex2hsl(nth($colors, 2))}, 1);\n --md-primary-fg-color--dark: hsla(#{hex2hsl(nth($colors, 3))}, 1);\n\n // Inverted text for lighter shades\n @if index(\"lime\" \"yellow\" \"amber\" \"orange\", $name) {\n --md-primary-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);\n } @else {\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: white\n// ----------------------------------------------------------------------------\n\n// Color palette\n[data-md-color-primary=\"white\"] {\n --md-primary-fg-color: hsla(0, 0%, 100%, 1);\n --md-primary-fg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-primary-fg-color--dark: hsla(0, 0%, 0%, 0.07);\n --md-primary-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);\n\n // Typeset color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n\n // [tablet portrait +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n\n // Search input\n .md-search__input {\n background-color: hsla(0, 0%, 0%, 0.07);\n\n // Search icon color\n + .md-search__icon {\n color: hsla(0, 0%, 0%, 0.87);\n }\n\n // Placeholder color\n &::placeholder {\n color: hsla(0, 0%, 0%, 0.54);\n }\n\n // Hovered search field\n &:hover {\n background-color: hsla(0, 0%, 0%, 0.32);\n }\n }\n }\n\n // [screen +]: Add bottom border for tabs\n @include break-from-device(screen) {\n\n // Navigation tabs\n .md-tabs {\n border-bottom: px2rem(1px) solid hsla(0, 0%, 0%, 0.07);\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: black\n// ----------------------------------------------------------------------------\n\n// Color palette\n[data-md-color-primary=\"black\"] {\n --md-primary-fg-color: hsla(0, 0%, 0%, 1);\n --md-primary-fg-color--light: hsla(0, 0%, 0%, 0.54);\n --md-primary-fg-color--dark: hsla(0, 0%, 0%, 1);\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Text color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n\n // Header\n .md-header {\n background-color: hsla(0, 0%, 0%, 1);\n }\n\n // [tablet portrait -]: Layered navigation\n @include break-to-device(tablet portrait) {\n\n // Repository information container\n .md-nav__source {\n background-color: hsla(0, 0%, 0%, 0.87);\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n\n // Search input\n .md-search__input {\n background-color: hsla(0, 0%, 100%, 0.12);\n\n // Search form on hover\n &:hover {\n background-color: hsla(0, 0%, 100%, 0.3);\n }\n }\n }\n\n // [tablet -]: Layered navigation\n @include break-to-device(tablet) {\n\n // Site title in main navigation\n html & .md-nav--primary .md-nav__title[for=\"__drawer\"] {\n background-color: hsla(0, 0%, 0%, 1);\n }\n }\n\n // [screen +]: Set background color for tabs\n @include break-from-device(screen) {\n\n // Navigation tabs\n .md-tabs {\n background-color: hsla(0, 0%, 0%, 1);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n///\n/// Device-specific breakpoints\n///\n/// @example\n/// $break-devices: (\n/// mobile: (\n/// portrait: 220px 479px,\n/// landscape: 480px 719px\n/// ),\n/// tablet: (\n/// portrait: 720px 959px,\n/// landscape: 960px 1219px\n/// ),\n/// screen: (\n/// small: 1220px 1599px,\n/// medium: 1600px 1999px,\n/// large: 2000px\n/// )\n/// );\n///\n$break-devices: () !default;\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n///\n/// Choose minimum and maximum device widths\n///\n@function break-select-min-max($devices) {\n $min: 1000000;\n $max: 0;\n @each $key, $value in $devices {\n @while type-of($value) == map {\n $value: break-select-min-max($value);\n }\n @if type-of($value) == list {\n @each $number in $value {\n @if type-of($number) == number {\n $min: min($number, $min);\n @if $max != null {\n $max: max($number, $max);\n }\n } @else {\n @error \"Invalid number: #{$number}\";\n }\n }\n } @else if type-of($value) == number {\n $min: min($value, $min);\n $max: null;\n } @else {\n @error \"Invalid value: #{$value}\";\n }\n }\n @return $min, $max;\n}\n\n///\n/// Select minimum and maximum widths for a device breakpoint\n///\n@function break-select-device($device) {\n $current: $break-devices;\n @for $n from 1 through length($device) {\n @if type-of($current) == map {\n $current: map-get($current, nth($device, $n));\n } @else {\n @error \"Invalid device map: #{$devices}\";\n }\n }\n @if type-of($current) == list or type-of($current) == number {\n $current: (default: $current);\n }\n @return break-select-min-max($current);\n}\n\n// ----------------------------------------------------------------------------\n// Mixins\n// ----------------------------------------------------------------------------\n\n///\n/// A minimum-maximum media query breakpoint\n///\n@mixin break-at($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (min-width: $breakpoint) {\n @content;\n }\n } @else if type-of($breakpoint) == list {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @if type-of($min) == number and type-of($max) == number {\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// An orientation media query breakpoint\n///\n@mixin break-at-orientation($breakpoint) {\n @if type-of($breakpoint) == string {\n @media screen and (orientation: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A maximum-aspect-ratio media query breakpoint\n///\n@mixin break-at-ratio($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (max-aspect-ratio: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A minimum-maximum media query device breakpoint\n///\n@mixin break-at-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n @if nth($breakpoint, 2) != null {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A minimum media query device breakpoint\n///\n@mixin break-from-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $min: nth($breakpoint, 1);\n @media screen and (min-width: $min) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A maximum media query device breakpoint\n///\n@mixin break-to-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $max: nth($breakpoint, 2);\n @media screen and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Only use dark mode on screens\n@media screen {\n\n // Slate theme, i.e. dark mode\n [data-md-color-scheme=\"slate\"] {\n\n // Slate's hue in the range [0,360] - change this variable to alter the tone\n // of the theme, e.g. to make it more redish or greenish. This is a slate-\n // specific variable, but the same approach may be adapted to custom themes.\n --md-hue: 232;\n\n // Default color shades\n --md-default-fg-color: hsla(var(--md-hue), 75%, 95%, 1);\n --md-default-fg-color--light: hsla(var(--md-hue), 75%, 90%, 0.62);\n --md-default-fg-color--lighter: hsla(var(--md-hue), 75%, 90%, 0.32);\n --md-default-fg-color--lightest: hsla(var(--md-hue), 75%, 90%, 0.12);\n --md-default-bg-color: hsla(var(--md-hue), 15%, 21%, 1);\n --md-default-bg-color--light: hsla(var(--md-hue), 15%, 21%, 0.54);\n --md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 21%, 0.26);\n --md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 21%, 0.07);\n\n // Code color shades\n --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1);\n --md-code-bg-color: hsla(var(--md-hue), 15%, 15%, 1);\n\n // Code highlighting color shades\n --md-code-hl-color: hsla(#{hex2hsl($clr-blue-a200)}, 0.15);\n --md-code-hl-number-color: hsla(6, 74%, 63%, 1);\n --md-code-hl-special-color: hsla(340, 83%, 66%, 1);\n --md-code-hl-function-color: hsla(291, 57%, 65%, 1);\n --md-code-hl-constant-color: hsla(250, 62%, 70%, 1);\n --md-code-hl-keyword-color: hsla(219, 66%, 64%, 1);\n --md-code-hl-string-color: hsla(150, 58%, 44%, 1);\n\n // Typeset color shades\n --md-typeset-a-color: var(--md-primary-fg-color--light);\n\n // Typeset `mark` color shades\n --md-typeset-mark-color: hsla(#{hex2hsl($clr-blue-a200)}, 0.3);\n\n // Typeset `kbd` color shades\n --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12);\n --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2);\n --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1);\n\n // Admonition color shades\n --md-admonition-bg-color: hsla(var(--md-hue), 0%, 100%, 0.025);\n\n // Footer color shades\n --md-footer-bg-color: hsla(var(--md-hue), 15%, 12%, 0.87);\n --md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 10%, 1);\n\n // Black and white primary colors\n &[data-md-color-primary=\"black\"],\n &[data-md-color-primary=\"white\"] {\n\n // Typeset color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-400)}, 1);\n }\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/docs_src/dotNET/ASPdotNET.md b/docs/dotNET/ASPdotNET.md similarity index 92% rename from docs_src/dotNET/ASPdotNET.md rename to docs/dotNET/ASPdotNET.md index 98a75d9..e884297 100644 --- a/docs_src/dotNET/ASPdotNET.md +++ b/docs/dotNET/ASPdotNET.md @@ -12,18 +12,18 @@ comments: true To get started with Yeoman, install [Node.js](https://nodejs.org/en/). The installer includes Node.js and [npm](https://www.npmjs.com/). - for Mac OS X + ```bash brew install node -``` +``` - for Windows OS + ```bash choco install nodejs ``` - -### Install [Yeoman](http://yeoman.io/) and [Bower](https://bower.io/) - +### Install [Yeoman](https://yeoman.io/) and [Bower](https://bower.io/) ```bash npm install -g yo @@ -32,30 +32,27 @@ npm install -g bower ``` ### Install [generator-aspnet](https://www.npmjs.com/package/generator-aspnet) - + ```bash npm install -g generator-aspnet ``` -Run with +Run with + ```bash yo aspnet ``` See also: [Building Projects with Yeoman on docs.asp.net](https://docs.microsoft.com/en-us/aspnet/core/client-side/yeoman) - ### Optionaly install the [yeoman extension](https://marketplace.visualstudio.com/items?itemName=samverschueren.yo) in Visual Studio Code - ## Architecture -[Onion Architecture In ASP.NET Core MVC](http://www.c-sharpcorner.com/article/onion-architecture-in-asp-net-core-mvc/) +[Onion Architecture In ASP.NET Core MVC](https://www.c-sharpcorner.com/article/onion-architecture-in-asp-net-core-mvc/) [Example of a Web API built on ASP.NET Core](https://github.com/juunas11/AspNetCoreApiExample/tree/basic-api) - - ## [Routing Examples](https://joonasw.net/view/attribute-routing-cheat-sheet-for-aspnet-core) ```csharp @@ -118,9 +115,9 @@ public class SelectionController : Controller // /users/123 [Route("{id:int}")] public IActionResult Int(int id) => Ok($"Looked up user id {id}"); - + // /users/joonas [Route("{name:alpha}")] -public IActionResult String(string name) => Ok($"User name {name}"); +public IActionResult String(string name) => Ok($"User name {name}"); } ``` diff --git a/docs/dotNET/ASPdotNET/index.html b/docs/dotNET/ASPdotNET/index.html deleted file mode 100644 index e9a1da6..0000000 --- a/docs/dotNET/ASPdotNET/index.html +++ /dev/null @@ -1,2152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - ASP.NET Core app - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - - - - -
    -
    - - - - - - - -

    ASP.NET Core app

    - -

    Using Yeoman to generate a ASP.NET Core app from a template

    -

    Install Node.js and npm

    -

    To get started with Yeoman, install Node.js. The installer includes Node.js and npm.

    -
      -
    • for Mac OS X
    • -
    -
    brew install node
    -
    - -
      -
    • for Windows OS
    • -
    -
    choco install nodejs
    -
    - -

    Install Yeoman and Bower

    -
    npm install -g yo
    -
    -npm install -g bower
    -
    - -

    Install generator-aspnet

    -
    npm install -g generator-aspnet
    -
    - -

    Run with

    -
    yo aspnet
    -
    - -

    See also: Building Projects with Yeoman on docs.asp.net

    -

    Optionaly install the yeoman extension in Visual Studio Code

    -

    Architecture

    -

    Onion Architecture In ASP.NET Core MVC

    -

    Example of a Web API built on ASP.NET Core

    -

    Routing Examples

    -
    public class TestController : Controller
    -{
    -
    -// /hello
    -[Route("/hello")]
    -public IActionResult Hello() => Ok("Hello");
    -
    -// /hi only GET method
    -[Route("/hi")] [HttpGet]
    -public IActionResult Hi() => Ok("Hi");
    -
    -//Alternative for previous
    -[HttpGet("/hi")]
    -public IActionResult Hi() => Ok("Hi");
    -}
    -
    -//Route prefix
    -[Route("test")]
    -public class TestController2 : Controller
    -{
    -//You can have multiple routes on an action
    -[Route("")] // /test
    -[Route("hello")]  // /test/hello
    -public IActionResult Hello() => Ok("Hello");
    -
    -// Maps to both: // /test/hi, and: // /hi
    -[Route("/hi")] // Overrides the prefix with /, you can also use ~/
    -[Route("hi")]
    -public IActionResult Hi() => Ok("Hi");
    -
    -// /test/greet/Joon -> maps Joon to the name parameter
    -[Route("greet/{name}")]
    -public IActionResult Greet(string name) => Ok($"Hello {name}!");
    -
    -//Parameters can be optional
    -// /test/greetopt -> name == null
    -// /test/greetopt/Joon -> name == Joon
    -[Route("greetopt/{name?}")]
    -public IActionResult GreetOptional(string name) => Ok(name == null ? "No name" : "Hi!");
    -}
    -
    -// You can use [controller], [action], and [area] to create generic templates
    -[Route("[controller]/[action]")]
    -public class MyController : Controller
    -{
    -// /my/info
    -public IActionResult Info() => Ok("Info");
    -// /my/i
    -[Route("/[controller]/i")]
    -public IActionResult Info2() => Ok("Info2"); }
    -
    -[Route("users")]
    -public class SelectionController : Controller
    -{
    -//You can use constraints to influence route selection
    -//Do not use for validation!
    -// /users/123
    -[Route("{id:int}")]
    -public IActionResult Int(int id) => Ok($"Looked up user id {id}");
    -
    -// /users/joonas
    -[Route("{name:alpha}")]
    -public IActionResult String(string name) => Ok($"User name {name}"); 
    -}
    -
    - - - - - - - - - -
    -
    -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs_src/dotNET/AkkadotNET.md b/docs/dotNET/AkkadotNET.md similarity index 65% rename from docs_src/dotNET/AkkadotNET.md rename to docs/dotNET/AkkadotNET.md index 5e2bd9d..24d360a 100644 --- a/docs_src/dotNET/AkkadotNET.md +++ b/docs/dotNET/AkkadotNET.md @@ -3,8 +3,8 @@ title: Akka.NET Examples category: dotNET tags: .NET C# Akka --- -# Akka.NET Examples +# Akka.NET Examples // To install Akka.NET Distributed Actor Framework, run the following command in the Package Manager Console @@ -12,9 +12,9 @@ tags: .NET C# Akka // PM> Install-Package Akka.Remote -// Installing with Topshelf is as easy as calling .exe install on the command line. +// Installing with Topshelf is as easy as calling `.exe` install on the command line. -```C# +```csharp using System; using System.Collections.Generic; using System.Linq; @@ -24,14 +24,14 @@ using System.Threading.Tasks; // Add these two lines using Akka; using Akka.Actor; -using Topshelf; // http://topshelf.readthedocs.io/en/latest/configuration/quickstart.html +using Topshelf; // https://topshelf.readthedocs.io/en/latest/configuration/quickstart.html internal class Program { - private static void Main(string[] args) - { - // ‘x’ exposes all of the host level configuration - HostFactory.Run(x => + private static void Main(string[] args) + { + // ‘x’ exposes all of the host level configuration + HostFactory.Run(x => { x.Service(s => // telling Topshelf that there is a service of type ActorService. service configuration options exposed through the ‘s’ parameter. { @@ -39,19 +39,19 @@ internal class Program s.WhenStarted(service => service.Start()); s.WhenStopped(service => service.Stop()); ////continue and restart directives are also available - //s.WhenPaused(service => service.Pause()); - //s.WhenContinued(service => service.Continue()); - //s.WhenShutdown(service => service.Shutdown()); - + //s.WhenPaused(service => service.Pause()); + //s.WhenContinued(service => service.Continue()); + //s.WhenShutdown(service => service.Shutdown()); + }); x.RunAsLocalSystem(); // service ‘run as’ the ‘local system’. Alternatively x.RunAsLocalSystem(); x.RunAs("username", "password"); x.RunAsPrompt(); x.UseAssemblyInfoForServiceInfo(); - - //x.SetDescription("Orchestrator Host"); - //x.SetDisplayName("Orchestrator"); // display name for the winservice in the windows service monitor + + //x.SetDescription("Orchestrator Host"); + //x.SetDisplayName("Orchestrator"); // display name for the winservice in the windows service monitor //x.SetServiceName("Orchestrator"); // service name for the winservice in the windows service monitor - //x.SetInstanceName("MyService"); // instance name of the service, which is combined with the base service name and separated by a $. + //x.SetInstanceName("MyService"); // instance name of the service, which is combined with the base service name and separated by a $. }); } } @@ -74,47 +74,47 @@ public class ActorService //this is where you stop your actor system await this.system.Terminate(); } - - private void Create() - { - // Create your actor and get a reference to it. - // This will be an "ActorRef", which is not a - // reference to the actual actor instance - // but rather a client or proxy to it. - var job = system.ActorOf("Job"); - //or: var myActor = system.ActorOf(Props.Create()); - - // Send a message to the actor - job.Tell(new Message("Hello World")); - } + + private void Create() + { + // Create your actor and get a reference to it. + // This will be an "ActorRef", which is not a + // reference to the actual actor instance + // but rather a client or proxy to it. + var job = system.ActorOf("Job"); + //or: var myActor = system.ActorOf(Props.Create()); + + // Send a message to the actor + job.Tell(new Message("Hello World")); + } } // Example immutable message class - C# 7.0 public class Message { - public Message(T data) - { - this.Data = data; - } - - public T Data { get; } - - // Allow convesion to a tuple - public void Deconstruct(out T data) { data = this.Data; } + public Message(T data) + { + this.Data = data; + } + + public T Data { get; } + + // Allow convesion to a tuple + public void Deconstruct(out T data) { data = this.Data; } } // Example of ReceiveActor public class JobActor: ReceiveActor { private readonly ILoggingAdapter log = Context.GetLogger(); - + public JobActor() { Receive>(message => { log.Info("Received String message: {0}", message.Data); - // Console.WriteLine(message.Data); - - // reply back + // Console.WriteLine(message.Data); + + // reply back Sender.Tell(message); }); } @@ -163,48 +163,48 @@ https://petabridge.com/blog/akka-actors-finite-state-machines-switchable-behavio public class FooActor : ReceiveActor, IWithUnboundedStash { - private Task _runningTask; - private CancellationTokenSource _cancel; - - public IStash Stash {get; set;} - - public FooActor(){ - _cancel = new CancellationTokenSource(); - Ready(); - } - - private void Ready(){ - Receive(s => { - var self = Self; // closure - _runningTask = Task.Run(() => { - // ... work - }, _cancel.Token).ContinueWith(x => - { - if(x.IsCancelled || x.IsFaulted) - return new Failed(); - return new Finished(); - }, TaskContinuationOptions.ExecuteSynchronously) - .PipeTo(self); - - // switch behavior - Become(Working); - }) - } - - private void Working(){ - Receive(cancel => { - _cancel.Cancel(); // cancel work - BecomeReady(); - }); - Receive(f => BecomeReady()); - Receive(f => BecomeReady()); - ReceiveAny(o => Stash.Stash()); - } - - private void BecomeReady(){ - _cancel = new CancellationTokenSource(); - Stash.UnstashAll(); - Become(Ready); - } + private Task _runningTask; + private CancellationTokenSource _cancel; + + public IStash Stash {get; set;} + + public FooActor(){ + _cancel = new CancellationTokenSource(); + Ready(); + } + + private void Ready(){ + Receive(s => { + var self = Self; // closure + _runningTask = Task.Run(() => { + // ... work + }, _cancel.Token).ContinueWith(x => + { + if(x.IsCancelled || x.IsFaulted) + return new Failed(); + return new Finished(); + }, TaskContinuationOptions.ExecuteSynchronously) + .PipeTo(self); + + // switch behavior + Become(Working); + }) + } + + private void Working(){ + Receive(cancel => { + _cancel.Cancel(); // cancel work + BecomeReady(); + }); + Receive(f => BecomeReady()); + Receive(f => BecomeReady()); + ReceiveAny(o => Stash.Stash()); + } + + private void BecomeReady(){ + _cancel = new CancellationTokenSource(); + Stash.UnstashAll(); + Become(Ready); + } } ``` diff --git a/docs/dotNET/AkkadotNET/index.html b/docs/dotNET/AkkadotNET/index.html deleted file mode 100644 index 72a7e2d..0000000 --- a/docs/dotNET/AkkadotNET/index.html +++ /dev/null @@ -1,2114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - Akka.NET Examples - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - -
    -
    -
    - - -
    -
    -
    - - -
    -
    - - - - - - - -

    Akka.NET Examples

    -

    // To install Akka.NET Distributed Actor Framework, run the following command in the Package Manager Console

    -

    // PM> Install-Package Akka

    -

    // PM> Install-Package Akka.Remote

    -

    // Installing with Topshelf is as easy as calling .exe install on the command line.

    -
    using System;
    -using System.Collections.Generic;
    -using System.Linq;
    -using System.Text;
    -using System.Threading.Tasks;
    -
    -// Add these two lines
    -using Akka;
    -using Akka.Actor;
    -using Topshelf;   // http://topshelf.readthedocs.io/en/latest/configuration/quickstart.html
    -
    -internal class Program
    -{
    -    private static void Main(string[] args)
    -    {
    -        // ‘x’ exposes all of the host level configuration
    -        HostFactory.Run(x =>
    -        {
    -            x.Service<ActorService>(s =>     //  telling Topshelf that there is a service of type ActorService. service configuration options exposed through the ‘s’ parameter.
    -            {
    -                s.ConstructUsing(name => new ActorService()); // build an instance of the service; new or pull from IoC container
    -                s.WhenStarted(service => service.Start());
    -                s.WhenStopped(service => service.Stop());
    -                ////continue and restart directives are also available
    -                //s.WhenPaused(service => service.Pause());
    -                //s.WhenContinued(service => service.Continue());
    -                //s.WhenShutdown(service => service.Shutdown());
    -
    -            });
    -
    -            x.RunAsLocalSystem(); // service ‘run as’ the ‘local system’. Alternatively x.RunAsLocalSystem(); x.RunAs("username", "password");  x.RunAsPrompt();
    -            x.UseAssemblyInfoForServiceInfo();
    -
    -            //x.SetDescription("Orchestrator Host"); 
    -            //x.SetDisplayName("Orchestrator"); // display name for the winservice in the windows service monitor
    -            //x.SetServiceName("Orchestrator"); // service name for the winservice in the windows service monitor
    -            //x.SetInstanceName("MyService"); // instance name of the service, which is combined with the base service name and separated by a $.
    -        });
    -    }
    -}
    -
    -// <summary>
    -/// This class acts as an interface between the application and TopShelf
    -/// </summary>
    -public class ActorService
    -{
    -    private ActorSystem system;
    -
    -    public void Start()
    -    {
    -        // Create a new actor system (a container for actors)
    -        this.system = ActorSystem.Create("MainSystem");
    -    }
    -
    -    public async void Stop()
    -    {
    -        //this is where you stop your actor system
    -        await this.system.Terminate();
    -    }
    -
    -    private void Create()
    -    {
    -        // Create your actor and get a reference to it.
    -        // This will be an "ActorRef", which is not a
    -        // reference to the actual actor instance
    -        // but rather a client or proxy to it.
    -        var job = system.ActorOf<JobActor>("Job");
    -        //or: var myActor = system.ActorOf(Props.Create<JobActor>());
    -
    -        // Send a message to the actor
    -        job.Tell(new Message<string>("Hello World"));
    -    }
    -}
    -
    -// Example immutable message class - C# 7.0
    -public class Message<T>
    -{
    -    public Message(T data)
    -    {
    -        this.Data = data;
    -    }
    -
    -    public T Data { get; }
    -
    -    // Allow convesion to a tuple 
    -    public void Deconstruct(out T data) { data = this.Data; }
    -}
    -
    -// Example of ReceiveActor
    -public class JobActor: ReceiveActor
    -{
    -  private readonly ILoggingAdapter log = Context.GetLogger();
    -
    -  public JobActor()
    -  {
    -    Receive<Message<string>>(message => {
    -      log.Info("Received String message: {0}", message.Data);
    -      // Console.WriteLine(message.Data);
    -
    -      // reply back
    -      Sender.Tell(message);
    -    });
    -  }
    -}
    -
    -
    -
    -// Example of untyped actor
    -
    -public class MyActor : UntypedActor
    -{
    -    private ActorRef logger = Context.ActorOf<LogActor>();
    -
    -    // if any child, e.g. the logger above. throws an exception
    -    // apply the rules below
    -    // e.g. Restart the child, if 10 exceptions occur in 30 seconds or
    -    // less, then stop the actor
    -    protected override SupervisorStrategy SupervisorStrategy()
    -    {
    -        return new OneForOneStrategy( //or AllForOneStrategy
    -            maxNumberOfRetries: 10,
    -            duration: TimeSpan.FromSeconds(30),
    -            decider: Decider.From(x =>
    -            {
    -                //Maybe we consider ArithmeticException to not be application critical
    -                //so we just ignore the error and keep going.
    -                if (x is ArithmeticException) return Directive.Resume;
    -                //Error that we cannot recover from, stop the failing actor
    -                else if (x is NotSupportedException) return Directive.Stop;
    -                //In all other cases, just restart the failing actor
    -                else return Directive.Restart;
    -             }));
    -    }
    -}
    -
    -// Example of long-running operation in an Actor - PipeTo / Become / Stash
    -
    -/*
    -If you stick a long-running operation inside your Receive method then your actors will be unable to process any messages, including system messages, until that operation finishes. And if it’s possible that the operation will never finish, it’s possible to deadlock your actor.
    -The solution to this is simple: you need to encapsulate any long-running I/O-bound or CPU-bound operations inside a Task and make it possible to cancel that task from within the actor.
    -Here’s an example of how you can use behavior switching, stashing, and control messages to do this.
    -
    -https://petabridge.com/blog/akka-actors-finite-state-machines-switchable-behavior/
    -
    -*/
    -public class FooActor : ReceiveActor, IWithUnboundedStash
    -{
    -
    -    private Task _runningTask;
    -    private CancellationTokenSource _cancel;
    -
    -    public IStash Stash {get; set;}
    -
    -    public FooActor(){
    -        _cancel = new CancellationTokenSource();
    -        Ready();
    -    }
    -
    -    private void Ready(){
    -        Receive<Start>(s => {
    -            var self = Self; // closure
    -            _runningTask = Task.Run(() => {
    -                // ... work
    -            }, _cancel.Token).ContinueWith(x =>
    -            {
    -                if(x.IsCancelled || x.IsFaulted)
    -                    return new Failed();
    -                return new Finished();
    -            }, TaskContinuationOptions.ExecuteSynchronously)
    -            .PipeTo(self);
    -
    -            // switch behavior
    -            Become(Working);
    -        })
    -    }
    -
    -    private void Working(){
    -        Receive<Cancel>(cancel => {
    -            _cancel.Cancel(); // cancel work
    -            BecomeReady();
    -        });
    -        Receive<Failed>(f => BecomeReady());
    -        Receive<Finished>(f => BecomeReady());
    -        ReceiveAny(o => Stash.Stash());
    -    }
    -
    -    private void BecomeReady(){
    -        _cancel = new CancellationTokenSource();
    -        Stash.UnstashAll();
    -        Become(Ready);
    -    }
    -}
    -
    - - - - - - - - - -
    -
    -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs_src/dotNET/C#.md b/docs/dotNET/C#.md similarity index 95% rename from docs_src/dotNET/C#.md rename to docs/dotNET/C#.md index 8a64e8e..66d16a1 100644 --- a/docs_src/dotNET/C#.md +++ b/docs/dotNET/C#.md @@ -2,17 +2,16 @@ title: C# Cheatsheet category: dotNET tags: .NET C# -comments: true +comments: true --- # C# Cheatsheets -[Quick Reference](http://www.digilife.be/quickreferences/qrc/core%20csharp%20and%20.net%20quick%20reference.pdf) +[Quick Reference](https://www.digilife.be/quickreferences/qrc/core%20csharp%20and%20.net%20quick%20reference.pdf) [Cheatsheet](https://www.cheatography.com/kimyo/cheat-sheets/c/) - -# C# 6.0 / 7.0 - what is new +## C# 6.0 / 7.0 - what is new ### Readonly properties @@ -34,7 +33,7 @@ public override string ToString() => "Hi!"; ```csharp using static System.String; -// also common: +// also common: // using static System.Math; // using static System.Linq.Enumerable; @@ -65,11 +64,11 @@ public static async Task MakeRequest() { var client = new System.Net.Http.HttpClient(); var streamTask = client.GetStringAsync("https://localHost:10000"); - try + try { var responseText = await streamTask; return responseText; - } + } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")) { return "Site Moved"; @@ -103,7 +102,7 @@ if (int.TryParse(input, out int result)) else WriteLine("Could not parse input"); ``` - + ### Tuples ```csharp @@ -168,4 +167,4 @@ public static IEnumerable AlphabetSubset3(char start, char end) yield return c; } } -``` \ No newline at end of file +``` diff --git a/docs/dotNET/C#/index.html b/docs/dotNET/C#/index.html deleted file mode 100644 index 36e8c8a..0000000 --- a/docs/dotNET/C#/index.html +++ /dev/null @@ -1,2053 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - C# Cheatsheet - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - -
    -
    -
    - - -
    -
    -
    - - -
    -
    - - - - - - - -

    C# Cheatsheets

    -

    Quick Reference

    -

    Cheatsheet

    -

    C# 6.0 / 7.0 - what is new

    -

    Readonly properties

    -
    public string FirstName { get; private set; }  // private set is accessible from the entire class
    -
    -public string LastName { get; } // accessible only in constructor
    -
    -public ICollection<double> Grades { get; } = new List<double>(); // property initializer
    -
    - -

    Expression-bodied function members

    -
    public override string ToString() => "Hi!";
    -
    - -

    Using static

    -
    using static System.String;
    -// also common: 
    -// using static System.Math;
    -// using static System.Linq.Enumerable;
    -
    -if (IsNullOrWhiteSpace(lastName))
    -  throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
    -
    - -

    Null checking

    -
    var first = person?.FirstName;
    -first = person?.FirstName ?? "Unspecified";
    -
    -// preferred event handing in C# 6:
    -this.SomethingHappened?.Invoke(this, eventArgs);
    -
    - -

    String interpolation

    -
    public string GetFormattedGradePoint() => $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";
    -
    - -

    Exception Filters

    -
    public static async Task<string> MakeRequest()
    -{
    -  var client = new System.Net.Http.HttpClient();
    -  var streamTask = client.GetStringAsync("https://localHost:10000");
    -  try 
    -  {
    -    var responseText = await streamTask;
    -    return responseText;
    -  } 
    -  catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    -  {
    -  return "Site Moved";
    -  }
    -}
    -
    - -

    List and dict initializers

    -
    private List<string> messages = new List<string>
    -{
    -  "Page not Found",
    -  "Page moved, but left a forwarding address.",
    -  "The web server can't come out to play today."
    -};
    -
    -private Dictionary<int, string> webErrors = new Dictionary<int, string>
    -{
    -  [404] = "Page not Found",
    -  [302] = "Page moved, but left a forwarding address.",
    -  [500] = "The web server can't come out to play today."
    -};
    -
    - -

    Out variables

    -
    if (int.TryParse(input, out int result))
    -    WriteLine(result);
    -else
    -    WriteLine("Could not parse input");
    -
    - -

    Tuples

    -
    var letters = ("a", "b");
    -
    -(string Alpha, string Beta) namedLetters = ("a", "b");
    -var alphabetStart = (Alpha: "a", Beta: "b");
    -
    -public class Point
    -{
    -  public Point(double x, double y)
    -  {
    -  this.X = x;
    -  this.Y = y;
    -  }
    -
    -  public double X { get; }
    -  public double Y { get; }
    -
    -  // Deconstruct method
    -  public void Deconstruct(out double x, out double y)
    -  {
    -  x = this.X;
    -  y = this.Y;
    -  }
    -}
    -
    - -

    Ref return values

    -
    public static ref int Find3(int[,] matrix, Func<int, bool> predicate)
    -{
    -  for (int i = 0; i < matrix.GetLength(0); i++)
    -             for (int j = 0; j < matrix.GetLength(1); j++)
    -                      if (predicate(matrix[i, j]))
    -                          return ref matrix[i, j];
    -  throw new InvalidOperationException("Not found");
    -}
    -ref var item = ref MatrixSearch.Find3(matrix, (val) => val == 42);
    -Console.WriteLine(item);
    -item = 24;
    -Console.WriteLine(matrix[4, 2]);
    -
    - -

    Local functions

    -
    public static IEnumerable<char> AlphabetSubset3(char start, char end)
    -{
    -    if ((start < 'a') || (start > 'z'))
    -        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    -    if ((end < 'a') || (end > 'z'))
    -        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");
    -    if (end <= start)
    -        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    -    return alphabetSubsetImplementation();
    -
    -    IEnumerable<char> alphabetSubsetImplementation()
    -    {
    -        for (var c = start; c < end; c++)
    -            yield return c;
    -    }
    -}
    -
    - - - - - - - - - -
    -
    -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs_src/dotNET/Multithreading.md b/docs/dotNET/Multithreading.md similarity index 100% rename from docs_src/dotNET/Multithreading.md rename to docs/dotNET/Multithreading.md diff --git a/docs/dotNET/Multithreading/index.html b/docs/dotNET/Multithreading/index.html deleted file mode 100644 index a8d9388..0000000 --- a/docs/dotNET/Multithreading/index.html +++ /dev/null @@ -1,1962 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - .NET Multithreading - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - -
    -
    -
    - - -
    -
    -
    - - - -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs_src/dotNET/WPF.md b/docs/dotNET/WPF.md similarity index 80% rename from docs_src/dotNET/WPF.md rename to docs/dotNET/WPF.md index f845918..8a0def5 100644 --- a/docs_src/dotNET/WPF.md +++ b/docs/dotNET/WPF.md @@ -7,20 +7,20 @@ comments: true ## Useful Links -[WPF tutorial](http://wpftutorial.net/) +[WPF tutorial](https://wpftutorial.net/) -[WPF Documentation](http://msdn.microsoft.com/en-us/library/vstudio/ms754130.aspx) +[WPF Documentation](https://msdn.microsoft.com/en-us/library/vstudio/ms754130.aspx) [WPF Samples](https://github.com/Microsoft/WPF-Samples) -[WPF Tools](http://www.codeproject.com/Articles/22126/Mole-For-Visual-Studio-Visualizer-For-All-Project) +[WPF Tools](https://www.codeproject.com/Articles/22126/Mole-For-Visual-Studio-Visualizer-For-All-Project) ### Application ```xml @@ -29,7 +29,7 @@ comments: true ### Commands -[WPF Commands](http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx) +[WPF Commands](https://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx) WPF provides a set of predefined commands. The command library consists of the following classes: ApplicationCommands, NavigationCommands, MediaCommands, EditingCommands, and the ComponentCommands. @@ -48,7 +48,7 @@ WPF provides a set of predefined commands. The command library consists of the f ``` @@ -56,8 +56,8 @@ WPF provides a set of predefined commands. The command library consists of the f ```xml @@ -92,7 +92,7 @@ WPF provides a set of predefined commands. The command library consists of the f ``` - + ### Triggers ```xml @@ -106,4 +106,3 @@ WPF provides a set of predefined commands. The command library consists of the f ``` - diff --git a/docs/dotNET/WPF/index.html b/docs/dotNET/WPF/index.html deleted file mode 100644 index 9ea06b4..0000000 --- a/docs/dotNET/WPF/index.html +++ /dev/null @@ -1,2108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - WPF - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - -
    -
    -
    - - -
    -
    -
    - - -
    -
    - - - - - - - -

    WPF

    - - -

    WPF tutorial

    -

    WPF Documentation

    -

    WPF Samples

    -

    WPF Tools

    -

    Application

    -
    <Application x:Class="ExpenseIt.App"
    -     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    -     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    -     StartupUri="MainWindow.xaml">
    -    <Application.Resources>
    -    </Application.Resources>
    -</Application>
    -
    - -

    Commands

    -

    WPF Commands

    -

    WPF provides a set of predefined commands. The command library consists of the following classes: ApplicationCommands, NavigationCommands, MediaCommands, EditingCommands, and the ComponentCommands.

    -
    <StackPanel>
    -
    -<StackPanel.ContextMenu>
    -    <ContextMenu>
    -      <MenuItem Command="ApplicationCommands.Properties" />
    -    </ContextMenu>
    -</StackPanel.ContextMenu>
    -  <Menu>
    -    <MenuItem Command="ApplicationCommands.Paste" />
    -  </Menu>
    -  <TextBox /></StackPanel>
    -
    -<Window.InputBindings>
    -  <KeyBinding Key="B"
    -              Modifiers="Control" 
    -              Command="ApplicationCommands.Open" /></Window.InputBindings>
    -
    - -

    Page

    -
    <Page
    -  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    -  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    -  x:Class="ExampleNamespace.ExampleCode"
    -  >
    -  <StackPanel>
    -    <Button>Button 1</Button>
    -    <Button>Button 2</Button>
    -    <Button>Button 3</Button>
    -  </StackPanel>
    -</Page>
    -
    - -

    Styles

    -
    <Window.Resources><!--A Style that affects all TextBlocks-->
    -<Style TargetType="TextBlock">
    -  <Setter Property="HorizontalAlignment" Value="Center" />
    -  <Setter Property="FontFamily" Value="Comic Sans MS"/>
    -  <Setter Property="FontSize" Value="14"/></Style></Window.Resources>
    -<!--A Style that extends the previous TextBlock Style--><!--This is a "named style" with an x:Key of TitleText-->
    -<Style BasedOn="{StaticResource {x:Type TextBlock}}"
    -       TargetType="TextBlock"
    -       x:Key="TitleText">
    -  <Setter Property="FontSize" Value="26"/>
    -  <Setter Property="Foreground">
    -  <Setter.Value>
    -      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
    -        <LinearGradientBrush.GradientStops>
    -          <GradientStop Offset="0.0" Color="#90DDDD" />
    -          <GradientStop Offset="1.0" Color="#5BFFFF" />
    -        </LinearGradientBrush.GradientStops>
    -      </LinearGradientBrush>
    -    </Setter.Value>
    -  </Setter></Style>
    -
    - -

    Triggers

    -
    <Style x:Key="SpecialButton" TargetType="{x:Type Button}">
    -  <Style.Triggers>
    -    <Trigger Property="Button.IsMouseOver" Value="true">
    -      <Setter Property = "Background" Value="Red"/>
    -    </Trigger>
    -    <Trigger Property="Button.IsPressed" Value="true">
    -      <Setter Property = "Foreground" Value="Green"/>
    -    </Trigger>
    -  </Style.Triggers></Style>
    -
    - - - - - - - - - -
    -
    -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index ed89ce1..0000000 --- a/docs/index.html +++ /dev/null @@ -1,1880 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - John's Cheatsheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    -
    - -
    - - - -
    - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - - - - - - -
    -
    -
    - - - -
    -
    - - - - - - - -

    Home

    - -

    You will find here a collection of cheatsheets, code templates and snippets that I have collected over the years...

    -

    Given that they were created for my own use, these notes are often very terse and dense. Thank you for your patience, while I am slowly improving their readability. I also have hundreds more to move to GitHub Pages :-)

    -

    In the meanwhile, feel free to use as you wish. Please email me suggestions and corrections.

    - - - - - - - -
    -
    -
    -
    - - - - -
    - - - - - - - - - \ No newline at end of file diff --git a/docs_src/index.md b/docs/index.md similarity index 86% rename from docs_src/index.md rename to docs/index.md index bc55506..8c45f8c 100644 --- a/docs_src/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ You will find here a collection of cheatsheets, code templates and snippets that I have collected over the years... -Given that they were created for my own use, these notes are often very terse and dense. Thank you for your patience, while I am slowly improving their readability. I also have hundreds more to move to GitHub Pages :-) +Given that they were created for my own use, these notes are often very terse and dense. Thank you for your patience, while I am slowly improving their readability. I also have hundreds more to move to GitHub Pages :-) -In the meanwhile, feel free to use as you wish. Please email me suggestions and corrections. +In the meanwhile, feel free to use as you wish. Please email me suggestions and corrections. diff --git a/docs/sitemap.xml b/docs/sitemap.xml deleted file mode 100644 index 11e6fdf..0000000 --- a/docs/sitemap.xml +++ /dev/null @@ -1,319 +0,0 @@ - - - http://john-cd.com/cheatsheets/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Hadoop_Ecosystem/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Install_Spark_2.3_Locally/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_APIs/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_Basics/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_Development_with_sbt_and_InteliJ/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_on_AWS_EMR/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_on_EC2/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Big_Data/Spark_on_Kubernetes/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Cloud/AWS/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Cloud/AWS_Lambda/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Cloud/Serverless/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Debug_Kubernetes/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Deploy_to_Kubernetes%20%20%28Helm%29/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Deploy_to_Kubernetes/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Docker/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Helm_Chart_Creation/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Kubernetes_Cheatsheet/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Kubernetes_Concepts/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Kubernetes_Examples/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Minikube_Install_in_Ubuntu_on_Windows/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Containers/Minikube_Install_on_Windows/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Data_Manipulation/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Data_Visualization/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Deep_Learning/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Dimensionality_Reduction/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Keras/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Machine_Learning/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/Recommenders/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Data_Science/scikit-learn/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Databases/Mongodb/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Databases/Redshift/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Databases/SQL/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/DevOps/CloudFormation/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/DevOps/Git/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/DevOps/Orchestrator_Scheduler/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Java/Gradle/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Java/Java/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Java/Log4j/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Java/Maven/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Java/Spring/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Linux/Linux/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Linux/Virtualization/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Markup_and_Documentation/Jekyll/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Markup_and_Documentation/Markdown/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Markup_and_Documentation/MkDocs/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Markup_and_Documentation/reStructuredText/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Microservices/Microservices/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Privacy/Privacy_engineering/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Python/Flask/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Python/Jupyter/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Python/Matplotlib/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Python/Python/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Python/Python3/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Akka/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Play_Framework/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Collections/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Database_Access/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Design_Patterns/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Generalities/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Language/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Testing/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scala_Types/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/Scaladoc/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Scala/sbt/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Search/ElasticSearch/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Search/Logstash/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Software_Development/Development_Tools/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Software_Development/Eclipse/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Software_Development/IntelliJ/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Web/Bootstrap/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Web/CORS/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Web/jQuery/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/Windows/Command_Prompt_Here/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/dotNET/ASPdotNET/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/dotNET/AkkadotNET/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/dotNET/C%23/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/dotNET/Multithreading/ - 2021-01-01 - daily - - http://john-cd.com/cheatsheets/dotNET/WPF/ - 2021-01-01 - daily - - \ No newline at end of file diff --git a/docs/sitemap.xml.gz b/docs/sitemap.xml.gz deleted file mode 100644 index 2a87979fd86dd1f1aa53bfff18b4199ee9f201b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 989 zcmV<310wt%iwFov$?jhQ|8r?{Wo=<_E_iKh0M*)0Q`YVWQ>aT|NNyk}YScng=tBHj;()g< zFj%Xy27IL^<5RUH9Wy#{(l_Dx>NW_aT|h8eD((_DXsM~uvDz9gRamnEm#bUHXw98a zHaT_vl&MAfAQ!lpPvqjhv}^PZ8O7X~b4zWW#99>xQcI}UImmKl=wkJO^?-S+#a_-Y z=s{+yNkNyfz00oa2aJbfb?5zaNg^<4QyD(C{Y8`nTtkR`VoI){d@T>L zir-#DiBj006D7(TFR0^Q8rQxKTT!GR#|-R;ddwg3RZO><8to~d-x!VmObH>byxD;6_Irh{h>;CSdN{5+ zE@LHM#ZRk*neN)AV>u(FL6rhGme`uLFxaq@h&q*`$~0I=&Z`P!iB=Xmb>*SPE%{28 zZMRi(vKDvKSwSLiA1AAGtp)v1`4bU?DV$mX$A_BCt9XqLeLs6?P^51e|6dCQO0+%3 z*j`Y-{u8ZhMAm0cT9zuT#f)w<1h30v(SMrJLrRuyNkw1?a#-}tTk!aPrCIWR)!8GF z4WhLRZA}wUv~jmwPtbb3CtN2NMBGoUHj+^D`-e=D=jB_AUd*c6{SWtZs_TBzVdbfA zSlyr(bNlDSUl)(bdA1t<66T6wj7Zr0XmToyl(v=)mmVP(G)Nn8Pphl{O?0r^1?1UZ L(sTKvD=`270-Nu0 diff --git a/docs_src/Big_Data/Spark_Development_with_sbt_and_InteliJ.md b/docs_src/Big_Data/Spark_Development_with_sbt_and_InteliJ.md deleted file mode 100644 index d8c5fd5..0000000 --- a/docs_src/Big_Data/Spark_Development_with_sbt_and_InteliJ.md +++ /dev/null @@ -1,50 +0,0 @@ -# Setup a Spark Development Environment with IntelliJ and sbt - -## Useful Links - -[ Hortonworks tutorial ]( https://hortonworks.com/tutorial/setting-up-a-spark-development-environment-with-scala/ ) - - -## Packaging and Submission Steps using sbt - -Package a jar containing your application: - -```shell -$ sbt package -... -[info] Packaging {..}/{..}/target/scala-2.11/simple-project_2.11-1.0.jar -``` - -Don't use ``sbt run`` - -Then use [spark submit] ( https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit ) - to run your application - -```sh -YOUR_SPARK_HOME/bin/spark-submit \ - --class "SimpleApp" \ - --master local[4] \ - target/scala-2.11/simple-project_2.11-1.0.jar -``` - -Open the Spark UI to monitor: [ http://localhost:4040 ]( http://localhost:4040 ) - - -## Plugins - -### sbt-spark-package - -The [ Sbt Plugin for Spark Packages ]( https://github.com/databricks/sbt-spark-package ) is a Sbt plugin that aims to simplify the use and development of Spark Packages. - -[ Blog ]( https://medium.com/@mrpowers/creating-a-spark-project-with-sbt-intellij-sbt-spark-package-and-friends-cc9108751c28 ) - - -### IntelliJ plugin for Spark - -Note: does not work with IntelliJ 2018.1 - -The [ IntelliJ plugin for Spark ]( https://plugins.jetbrains.com/plugin/10412-spark ) supports for deployment spark application and cluster monitoring. - -- To install, download the plugin -- File > Settings, Plugins tab, browse repos... point to the zip file - diff --git a/docs_src/Java/Java.md b/docs_src/Java/Java.md deleted file mode 100644 index 713bf12..0000000 --- a/docs_src/Java/Java.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Java Pointers -category: java -tags: libraries tools -comments: true ---- - -## Install [Java](https://www.java.com/en/) - -[JDK download](http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html) - -```bash -java -version -``` - -## Java Tools - -[List 1](https://www.loggly.com/blog/8-tools-for-every-java-developers-toolkit/) - -[List 2](https://blog.newrelic.com/2014/05/21/toolsforjavadevelopers/) - -- [Eclipse](https://eclipse.org/downloads/) IDE -- [Maven](https://maven.apache.org/download.cgi) or Graddle build tool -- [Nexus](http://www.sonatype.org/nexus/) private repository -- [Maven public repository](http://mvnrepository.com/) -- [Phabrikator](https://www.phacility.com/) code review - - [Phabrikator blog](http://scn.sap.com/community/abap/blog/2014/11/24/code-review-with-phabricator--an-open-source-software-engineering-platform) -- [Jenkins](https://jenkins.io/) CI / CD automation server -- [JProfiler](http://www.ej-technologies.com/products/jprofiler/overview.html) -- [FindBugs](http://findbugs.sourceforge.net/) static analysis or [Checker Framework](http://types.cs.washington.edu/checker-framework/) -- [Checkstyle](http://checkstyle.sourceforge.net/) coding standard checker - - [Style guidelines](http://logging.apache.org/log4j/2.x/javastyle.html) - -## Java Libraries - -[Libraries](https://www.devsaran.com/blog/16-java-development-tools-web-developers) - -- [Log4j](https://logging.apache.org/) -- [Spring](http://www.spring.io) - - [Spring Cloud for Amazon Web Services](https://cloud.spring.io/spring-cloud-aws/) - - [Spring boot code generator](https://start.spring.io/) -- [Apache Commons](https://commons.apache.org/) -- [Guava](https://github.com/google/guava) -- [Jackson JSON](http://wiki.fasterxml.com/JacksonHome) or [GSON](https://github.com/google/gson/blob/master/UserGuide.md) -- [Hibernate](http://hibernate.org/orm/) -on the JVM. -- [Play framework](https://www.playframework.com/) -- [Spark web microframework](http://sparkjava.com/) -- [Akka](http://akka.io/) - actor model, to build highly concurrent, distributed, and resilient message-driven applications - diff --git a/docs_src/Linux/Virtualization.md b/docs_src/Linux/Virtualization.md deleted file mode 100644 index b45e7e0..0000000 --- a/docs_src/Linux/Virtualization.md +++ /dev/null @@ -1,12 +0,0 @@ -# Virtualization - -[Comparison of platform virtual machines]( http://en.wikipedia.org/wiki/Comparison_of_platform_virtual_machines ) - -[Linux KVM]( http://www.linux-kvm.org/ ) - -[Xen]( http://en.wikipedia.org/wiki/Xen ) - -[VMware ESX]( http://en.wikipedia.org/wiki/VMware_ESX ) - -[vSphere]( http://en.wikipedia.org/wiki/VSphere ) - diff --git a/docs_src/Markup_and_Documentation/reStructuredText.md b/docs_src/Markup_and_Documentation/reStructuredText.md deleted file mode 100644 index f4b1b6a..0000000 --- a/docs_src/Markup_and_Documentation/reStructuredText.md +++ /dev/null @@ -1,344 +0,0 @@ ---- -title: reStructuredText Cheatsheet -category: markup -tags: python ---- - -# [reStructuredText](http://docutils.sourceforge.net/rst.html) - -[reStructuredText Quick Ref](http://docutils.sourceforge.net/docs/user/rst/quickref.html) - -[reStructuredText Cheat Sheet](http://docutils.sourceforge.net/docs/user/rst/cheatsheet.txt) (see below) - -## reST Short Overview - -All reST files use an indentation of 3 spaces; no tabs are allowed. -The maximum line length is 80 characters for normal text, but tables, -deeply indented code samples and long links may extend beyond that. -Code example bodies should use normal Python 4-space indentation. -Paragraphs are simply chunks of text separated by one or more blank lines. -As in Python, indentation is significant in reST, so all lines of the same -paragraph must be left-aligned to the same level of indentation. - -Section headers are created by underlining (and optionally overlining) -the section title with a punctuation character, at least as long as the text: - - ================= - This is a heading - ================= - # with overline, for parts - * with overline, for chapters - = for sections - - for subsections - ^ for subsubsections - " for paragraphs - - one asterisk: *text* for emphasis (italics), - two asterisks: **text** for strong emphasis (boldface), and - backquotes: ``text`` for code samples. - escape with a backslash \ - - * This is a bulleted list. - * It has two items, the second - item uses two lines. - - 1. This is a numbered list. - 2. It has two items too. - - . This is a numbered list. - . It has two items too. - -Nested lists are possible, but be aware that they must be separated from the -parent list items by blank lines - -## Source Code Double Colon - -``` -This is a normal text paragraph. The next paragraph is a code sample:: - - It is not processed in any way, except - that the indentation is removed. - - It can span multiple lines. - -This is a normal text paragraph again. -``` - -## Links - - `Link text `_ for inline web links. - - -## Definitions - - term (up to a line of text) - Definition of the term, which must be indented and - can even consist of multiple paragraphs - - next term - Description. - -### Footnotes - - Lorem ipsum [#]_ dolor sit amet ... [#]_ - - -## Use of reStructuredText in Python docstrings - -See http://infinitemonkeycorps.net/docs/pph/ - -``` - # Typical function documentation: - - :param volume_id: The ID of the EBS volume to be attached. - :type volume_id: str - - :param instance_id: The ID of the EC2 instance - :type instance_id: str - - :return: `Reverse geocoder return value`_ dictionary giving closest - address(es) to `(lat, lng)` - :rtype: dict - :raises GoogleMapsError: If the coordinates could not be reverse geocoded. - - Keyword arguments and return value are identical to those of :meth:`geocode()`. - - .. _`Reverse geocoder return value`: - http://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding -``` - -- Normal docstring formatting conventions apply: see PEP 257. -- Identifier references go in \`backticks\`. -- `:param lat: some text` _documents parameters_ -- `:type lat: float` _documents parameter types_ -- `:return:` dictionary giving some info... _documents return values_ -- `:rtype: dict` _documents return type_ -- `:raises SomeError:` sometext... _documents exceptions raised_ -- `>>>` _starts a doctest and is automatically formatted as code_ -- Code can also be indicated by indenting four spaces or preceding with `::` and a blank line -- Link to other methods, functions, classes, modules with :meth:`mymethod`, -- :func:`myfunc`, :class:`myclass`, and :mod:`mymodule`. -- Hyperlink names go in backticks with a trailing underscore: `Google`_ -- Targets can be defined anywhere with: `.. _Google: http://www.google.com/` - - -## Explicit Markup - -An explicit markup block begins with a line starting with .. followed by -whitespace and is terminated by the next paragraph at the same level of -indentation. (There needs to be a blank line between explicit markup -and normal paragraphs. - - .. sectionauthor:: Guido van Rossum - - .. rubric:: Footnotes - - .. [#] Text of the first footnote. - .. [#] Text of the second footnote. - - - :mod:`parrot` -- Dead parrot access - =================================== - - .. module:: parrot - :platform: Unix, Windows - :synopsis: Analyze and reanimate dead parrots. - .. moduleauthor:: Eric Cleese - .. moduleauthor:: John Idle - - .. function:: repeat([repeat=3[, number=1000000]]) - repeat(y, z) - :bar: no - - Return a line of text input from the user. - - - .. class:: Spam - - Description of the class. - - .. data:: ham - - Description of the attribute. - - - -## Inline markup - - :rolename:`content` or :role:`title ` - - :meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text. - -The following roles refer to objects in modules and are possibly hyperlinked -if a matching identifier is found: - -**mod** - -The name of a module; a dotted name may be used. This should also be used for package names. - -**func** - -The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers. - -**data** - -The name of a module-level variable or constant. - -**const** - -The name of a “defined” constant. This may be a C-language #define or a Python variable that is not intended to be changed. - -**class** - -A class name; a dotted name may be used. - -**meth** - -The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used. - -**attr** - -The name of a data attribute of an object. - -**exc** - -The name of an exception. A dotted name may be used. - - -# Official reStructuredText Cheatsheet - - ===================================================== - The reStructuredText_ Cheat Sheet: Syntax Reminders - ===================================================== - :Info: See for introductory docs. - :Author: David Goodger - :Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $ - :Revision: $Revision: 7612 $ - :Description: This is a "docinfo block", or bibliographic field list - - .. NOTE:: If you are reading this as HTML, please read - ``_ instead to see the input syntax examples! - - Section Structure - ================= - Section titles are underlined or overlined & underlined. - - Body Elements - ============= - Grid table: - - +--------------------------------+-----------------------------------+ - | Paragraphs are flush-left, | Literal block, preceded by "::":: | - | separated by blank lines. | | - | | Indented | - | Block quotes are indented. | | - +--------------------------------+ or:: | - | >>> print 'Doctest block' | | - | Doctest block | > Quoted | - +--------------------------------+-----------------------------------+ - | | Line blocks preserve line breaks & indents. [new in 0.3.6] | - | | Useful for addresses, verse, and adornment-free lists; long | - | lines can be wrapped with continuation lines. | - +--------------------------------------------------------------------+ - - Simple tables: - - ================ ============================================================ - List Type Examples (syntax in the `text source `_) - ================ ============================================================ - Bullet list * items begin with "-", "+", or "*" - Enumerated list 1. items use any variation of "1.", "A)", and "(i)" - #. also auto-enumerated - Definition list Term is flush-left : optional classifier - Definition is indented, no blank line between - Field list :field name: field body - Option list -o at least 2 spaces between option & description - ================ ============================================================ - - ================ ============================================================ - Explicit Markup Examples (visible in the `text source`_) - ================ ============================================================ - Footnote .. [1] Manually numbered or [#] auto-numbered - (even [#labelled]) or [*] auto-symbol - Citation .. [CIT2002] A citation. - Hyperlink Target .. _reStructuredText: http://docutils.sf.net/rst.html - .. _indirect target: reStructuredText_ - .. _internal target: - Anonymous Target __ http://docutils.sf.net/docs/ref/rst/restructuredtext.html - Directive ("::") .. image:: images/biohazard.png - Substitution Def .. |substitution| replace:: like an inline directive - Comment .. is anything else - Empty Comment (".." on a line by itself, with blank lines before & after, - used to separate indentation contexts) - ================ ============================================================ - - Inline Markup - ============= - *emphasis*; **strong emphasis**; `interpreted text`; `interpreted text - with role`:emphasis:; ``inline literal text``; standalone hyperlink, - http://docutils.sourceforge.net; named reference, reStructuredText_; - `anonymous reference`__; footnote reference, [1]_; citation reference, - [CIT2002]_; |substitution|; _`inline internal target`. - - Directive Quick Reference - ========================= - See for full info. - - ================ ============================================================ - Directive Name Description (Docutils version added to, in [brackets]) - ================ ============================================================ - attention Specific admonition; also "caution", "danger", - "error", "hint", "important", "note", "tip", "warning" - admonition Generic titled admonition: ``.. admonition:: By The Way`` - image ``.. image:: picture.png``; many options possible - figure Like "image", but with optional caption and legend - topic ``.. topic:: Title``; like a mini section - sidebar ``.. sidebar:: Title``; like a mini parallel document - parsed-literal A literal block with parsed inline markup - rubric ``.. rubric:: Informal Heading`` - epigraph Block quote with class="epigraph" - highlights Block quote with class="highlights" - pull-quote Block quote with class="pull-quote" - compound Compound paragraphs [0.3.6] - container Generic block-level container element [0.3.10] - table Create a titled table [0.3.1] - list-table Create a table from a uniform two-level bullet list [0.3.8] - csv-table Create a table from CSV data [0.3.4] - contents Generate a table of contents - sectnum Automatically number sections, subsections, etc. - header, footer Create document decorations [0.3.8] - target-notes Create an explicit footnote for each external target - math Mathematical notation (input in LaTeX format) - meta HTML-specific metadata - include Read an external reST file as if it were inline - raw Non-reST data passed untouched to the Writer - replace Replacement text for substitution definitions - unicode Unicode character code conversion for substitution defs - date Generates today's date; for substitution defs - class Set a "class" attribute on the next element - role Create a custom interpreted text role [0.3.2] - default-role Set the default interpreted text role [0.3.10] - title Set the metadata document title [0.3.10] - ================ ============================================================ - - Interpreted Text Role Quick Reference - ===================================== - See for full info. - - ================ ============================================================ - Role Name Description - ================ ============================================================ - emphasis Equivalent to *emphasis* - literal Equivalent to ``literal`` but processes backslash escapes - math Mathematical notation (input in LaTeX format) - PEP Reference to a numbered Python Enhancement Proposal - RFC Reference to a numbered Internet Request For Comments - raw For non-reST data; cannot be used directly (see docs) [0.3.6] - strong Equivalent to **strong** - sub Subscript - sup Superscript - title Title reference (book, etc.); standard default role - ================ ============================================================ - - - diff --git a/drafts/Analytical_Tools.md b/drafts/Analytical_Tools.md index 997fe8b..68d5490 100644 --- a/drafts/Analytical_Tools.md +++ b/drafts/Analytical_Tools.md @@ -2,98 +2,96 @@ ## General -[List of information graphics software - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/List_of_graphing_software ) +[List of information graphics software - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/List_of_graphing_software ) -[List of numerical analysis software - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/List_of_numerical_analysis_software ) +[List of numerical analysis software - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/List_of_numerical_analysis_software ) -[List of statistical packages - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/List_of_statistical_packages ) +[List of statistical packages - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/List_of_statistical_packages ) -[Comparison of numerical analysis software - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Comparison_of_numerical_analysis_software ) +[Comparison of numerical analysis software - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Comparison_of_numerical_analysis_software ) -[Comparison of statistical packages - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Econometric_software ) +[Comparison of statistical packages - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Econometric_software ) -[DataScope- Statistical Graphics]( http://www.datascope.be/ ) +[DataScope- Statistical Graphics]( https://www.datascope.be/ ) -[FlowingData - Data Visualization, Infographics, and Statistics]( http://flowingdata.com/ ) +[FlowingData - Data Visualization, Infographics, and Statistics]( https://flowingdata.com/ ) -[Free statistical software - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Free_statistical_software ) +[Free statistical software - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Free_statistical_software ) -[FusionCharts - Product Tour]( http://www.fusioncharts.com/tour/?gclid=COLVhLedw6sCFQoZQgodXRfnrw#!stunning-looks ) +[FusionCharts - Product Tour]( https://www.fusioncharts.com/tour/?gclid=COLVhLedw6sCFQoZQgodXRfnrw#!stunning-looks ) -[GNU Octave - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/GNU_Octave ) +[GNU Octave - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/GNU_Octave ) -[Graph Visualization and Social Network Analysis Software - Navigator - TouchGraph.com]( http://www.touchgraph.com/navigator ) +[Graph Visualization and Social Network Analysis Software - Navigator - TouchGraph.com]( https://www.touchgraph.com/navigator ) -[gretl - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Gretl ) +[gretl - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Gretl ) -[hakia.com]( http://www.hakia.com/ ) +[hakia.com]( https://www.hakia.com/ ) -[OpenCalais]( http://www.opencalais.com/ ) +[OpenCalais]( https://www.opencalais.com/ ) -[TextWise LLC]( http://textwise.com/ ) +[TextWise LLC]( https://textwise.com/ ) -[API Overview - TextWise LLC]( http://textwise.com/api ) +[API Overview - TextWise LLC]( https://textwise.com/api ) -[IBM - United States]( http://www.ibm.com/us/en/ ) +[IBM - United States]( https://www.ibm.com/us/en/ ) -[Information visualization - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Information_visualization ) +[Information visualization - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Information_visualization ) -[Manning & Napier Associates, LLC]( http://www.manningnapierassociates.com/ ) +[Manning & Napier Associates, LLC]( https://www.manningnapierassociates.com/ ) -[Miner3D - Visual Data Analysis Software for Business Intelligence and Science]( http://www.miner3d.com/ ) +[Miner3D - Visual Data Analysis Software for Business Intelligence and Science]( https://www.miner3d.com/ ) -[mloss]( http://www.mloss.org/software/ ) +[mloss]( https://www.mloss.org/software/ ) -[NetBase - Social Media Consumer Insights, Market Analysis & Research Tools]( http://www.netbase.com/ ) +[NetBase - Social Media Consumer Insights, Market Analysis & Research Tools]( https://www.netbase.com/ ) -[Powerset - CrunchBase Profile]( http://www.crunchbase.com/company/powerset ) +[Powerset - CrunchBase Profile]( https://www.crunchbase.com/company/powerset ) -[RapidMiner - Wikipedia, the free encyclopedia (2)]( http://en.wikipedia.org/wiki/RapidMiner#cite_note-2 ) +[RapidMiner - Wikipedia, the free encyclopedia (2)]( https://en.wikipedia.org/wiki/RapidMiner#cite_note-2 ) -[RapidMiner - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/RapidMiner ) +[RapidMiner - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/RapidMiner ) -[R Commander - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/R_Commander ) +[R Commander - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/R_Commander ) -[R (programming language) - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/R_(programming_language) ) +[R (programming language) - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/R_(programming_language) ) -[SAS (software) - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/SAS_(software) ) +[SAS (software) - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/SAS_(software) ) -[Software- Visualization and Data Mining]( http://www.kdnuggets.com/software/visualization.html ) +[Software- Visualization and Data Mining]( https://www.kdnuggets.com/software/visualization.html ) -[Splunking Big Data]( http://www.splunk.com/view/SP-CAAAGFH ) +[Splunking Big Data]( https://www.splunk.com/view/SP-CAAAGFH ) -[SPP - Scalable Visual Analytics - Interactive Visual Analysis Systems of Complex Information Spaces]( http://www.visualanalytics.de/ ) +[SPP - Scalable Visual Analytics - Interactive Visual Analysis Systems of Complex Information Spaces]( https://www.visualanalytics.de/ ) -[SPSS PPC Resources - IBM SPSS Predictive Analytics Demo - od_spssrc_spss_statistics_the_analytic_professional]( http://forms.cognos.com/?elqPURLPage=4461&offid=od_spssrc_spss_statistics_the_analytic_professional&mc=-web_google_display ) +[SPSS PPC Resources - IBM SPSS Predictive Analytics Demo - od_spssrc_spss_statistics_the_analytic_professional]( https://forms.cognos.com/?elqPURLPage=4461&offid=od_spssrc_spss_statistics_the_analytic_professional&mc=-web_google_display ) -[Starlight Information Visualization System - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Starlight_Information_Visualization_System ) +[Starlight Information Visualization System - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Starlight_Information_Visualization_System ) -[Stata - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Stata ) +[Stata - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Stata ) [Subscription databases order form - European Patent Office]( https://secure.epo.org/products/patent/index.en.php ) -[SYSTAT - Products - SYSTAT Statistical Software Package]( http://www.systat.com/SystatProducts.aspx?gclid=CM3S_vOBw6sCFcsaQgode0bIuA ) +[SYSTAT - Products - SYSTAT Statistical Software Package]( https://www.systat.com/SystatProducts.aspx?gclid=CM3S_vOBw6sCFcsaQgode0bIuA ) -[Tableau Desktop - Tableau Software]( http://www.tableausoftware.com/products/desktop ) +[Tableau Desktop - Tableau Software]( https://www.tableausoftware.com/products/desktop ) -[TIBCO Spotfire - Business Intelligence Analytics Software & Data Visualization]( http://spotfire.tibco.com/ ) +[TIBCO Spotfire - Business Intelligence Analytics Software & Data Visualization]( https://spotfire.tibco.com/ ) -[VisMaster » Visual Analytics – Mastering the Information Age]( http://www.vismaster.eu/ ) +[VisMaster » Visual Analytics – Mastering the Information Age]( https://www.vismaster.eu/ ) -[Visual Analytics Digital Library]( http://vadl.cc.gatech.edu/ ) +[Visual Analytics Digital Library]( https://vadl.cc.gatech.edu/ ) -[Visual analytics - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Visual_analytics ) +[Visual analytics - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Visual_analytics ) [Weka (machine learning) - Wikipedia, the free encyclopedia (2)]( https://en.wikipedia.org/wiki/Weka_(machine_learning) ) -[Weka (machine learning) - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Weka_(machine_learning) ) +[Weka (machine learning) - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Weka_(machine_learning) ) ## Patent Analytics [Patent information services for experts]( https://data.epo.org/expert-services/start.html? ) -[Patent map - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Patent_map ) - -[Patent visualisation - Wikipedia, the free encyclopedia]( http://en.wikipedia.org/wiki/Patent_visualisation ) - +[Patent map - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Patent_map ) +[Patent visualisation - Wikipedia, the free encyclopedia]( https://en.wikipedia.org/wiki/Patent_visualisation ) diff --git a/drafts/Azure.md b/drafts/Azure.md index 539aa29..6025019 100644 --- a/drafts/Azure.md +++ b/drafts/Azure.md @@ -1,3 +1,3 @@ # Azure -[ Azure Cosmos DB – Globally Distributed Database Service - Microsoft Azure ]( https://azure.microsoft.com/en-us/services/cosmos-db/ ) \ No newline at end of file +[Azure Cosmos DB – Globally Distributed Database Service - Microsoft Azure ]( https://azure.microsoft.com/en-us/services/cosmos-db/ ) diff --git a/drafts/Citizen_developer_tools.md b/drafts/Citizen_developer_tools.md index 953c7dd..dcc5abe 100644 --- a/drafts/Citizen_developer_tools.md +++ b/drafts/Citizen_developer_tools.md @@ -1,9 +1,8 @@ - -## Citizen Developer tools +# Citizen Developer tools - Outsystems - Mendix - Betty Blocks - Microsoft PowerApps/Flow - Salesforce Lightning -- Appian \ No newline at end of file +- Appian diff --git a/drafts/Cloud_Computing.md b/drafts/Cloud_Computing.md index 39bc334..fa59c2d 100644 --- a/drafts/Cloud_Computing.md +++ b/drafts/Cloud_Computing.md @@ -1,7 +1,6 @@ +# Cloud Computing IaaS Platform -## Cloud Computing IaaS Platform +[CloudStack]( https://en.wikipedia.org/wiki/CloudStack ) -[CloudStack]( http://en.wikipedia.org/wiki/CloudStack ) - -[OpenStack]( http://en.wikipedia.org/wiki/OpenStack ) +[OpenStack]( https://en.wikipedia.org/wiki/OpenStack ) diff --git a/drafts/DataScience.md b/drafts/DataScience.md index b0f961d..0e82a84 100644 --- a/drafts/DataScience.md +++ b/drafts/DataScience.md @@ -1,15 +1,13 @@ +# Basics -## Basics - -[Introduction to Machine Learning]( https://developers.google.com/machine-learning/crash-course/ml-intro ) +[Introduction to Machine Learning]( https://developers.google.com/machine-learning/crash-course/ml-intro ) [School of AI - Udacity]( https://www.udacity.com/school-of-ai ) - ## Data Science Books -[Practical Data Science Cookbook]( http://www.amazon.com/Practical-Data-Science-Cookbook-Ojeda/dp/1783980249/ref=sr_1_49?ie=UTF8&qid=1415658223&sr=8-49&keywords=graph+database ) +[Practical Data Science Cookbook]( https://www.amazon.com/Practical-Data-Science-Cookbook-Ojeda/dp/1783980249/ref=sr_1_49?ie=UTF8&qid=1415658223&sr=8-49&keywords=graph+database ) ## Recommendation engines @@ -17,10 +15,10 @@ ## Semantic Search -[Build Your Own Semantic Search Engine With Hakia's APIs - TechCrunch ]( http://techcrunch.com/2008/06/19/build-your-own-semenatic-search-engine-with-hakias-apis/ ) +[Build Your Own Semantic Search Engine With Hakia's APIs - TechCrunch]( https://techcrunch.com/2008/06/19/build-your-own-semenatic-search-engine-with-hakias-apis/ ) [How To Create Natural Language Semantic Search For Arbitrary Objects With Deep Learning] -( https://towardsdatascience.com/semantic-code-search-3cd6d244a39c ) +( ) [Code Search on Kubeflow]( https://github.com/kubeflow/examples/tree/master/code_search ) @@ -48,9 +46,9 @@ ## Reinforcement Learning -[Reinforcement Learning - A Deep Dive]( https://www.toptal.com/machine-learning/deep-dive-into-reinforcement-learning ) +[Reinforcement Learning - A Deep Dive]( https://www.toptal.com/machine-learning/deep-dive-into-reinforcement-learning ) -[Rainbow- Combining Improvements in Deep Reinforcement Learning]( https://arxiv.org/abs/1710.02298 ) +[Rainbow- Combining Improvements in Deep Reinforcement Learning]( https://arxiv.org/abs/1710.02298 ) ## Probabilistic Programming in Python @@ -62,7 +60,7 @@ [Bayesian ChangePoint]( https://cscherrer.github.io/post/bayesian-changepoint/ ) -[Bayesian Inference for Hiring Engineers]( https://triplebyte.com/blog/bayesian-inference-for-hiring-engineers?ref=20180702_blog_bayes_email ) +[Bayesian Inference for Hiring Engineers]( https://triplebyte.com/blog/bayesian-inference-for-hiring-engineers?ref=20180702_blog_bayes_email ) [Uber Open Sources Pyro, a Deep Probabilistic Programming Language]( https://eng.uber.com/pyro/ ) @@ -80,7 +78,7 @@ Shapley values help us think through how to attribute cause in black-box models. [Introduction to TensorFlow Lite]( https://www.tensorflow.org/mobile/tflite/ ) -[PyTorch]( http://pytorch.org/ ) +[PyTorch]( https://pytorch.org/ ) [How to build a deep learning model in 15 minutes – tech-at-instacart]( https://tech.instacart.com/how-to-build-a-deep-learning-model-in-15-minutes-a3684c6f71e ) @@ -96,8 +94,7 @@ Shapley values help us think through how to attribute cause in black-box models. ### LSTMs -[Exploring LSTMs]( http://blog.echen.me/2017/05/30/exploring-lstms/?utm_source=Mailing+list&utm_campaign=479f35fbcc-Kaggle_Newsletter_06-29-2017&utm_medium=email&utm_term=0_f42f9df1e1-479f35fbcc-399045217 ) - +[Exploring LSTMs]( https://blog.echen.me/2017/05/30/exploring-lstms/?utm_source=Mailing+list&utm_campaign=479f35fbcc-Kaggle_Newsletter_06-29-2017&utm_medium=email&utm_term=0_f42f9df1e1-479f35fbcc-399045217 ) ## MLOps @@ -111,9 +108,9 @@ Taking the pain out of data access and distribution Intake is a lightweight package for finding, investigating, loading and disseminating data. It will appeal to different groups for some of the reasons below, but is useful for all and acts as a common platform that everyone can use to smooth the progression of data from developers and providers to users. -## AWS +## AWS -[Amazon Pinpoint campaigns driven by machine learning on Amazon SageMaker - AWS Machine Learning Blog]( https://aws.amazon.com/blogs/machine-learning/amazon-pinpoint-campaigns-driven-by-machine-learning-on-amazon-sagemaker/ ) +[Amazon Pinpoint campaigns driven by machine learning on Amazon SageMaker - AWS Machine Learning Blog]( https://aws.amazon.com/blogs/machine-learning/amazon-pinpoint-campaigns-driven-by-machine-learning-on-amazon-sagemaker/ ) ## PipelineAI @@ -124,4 +121,3 @@ Intake is a lightweight package for finding, investigating, loading and dissemin [PipelineAI GitHub]( https://github.com/PipelineAI/pipeline/tree/master/docs/quickstart/ ) [PipelineAI YouTube]( https://www.youtube.com/c/PipelineAI/ ) - diff --git a/drafts/Data_Visualization.md b/drafts/Data_Visualization.md index a20e22a..8bf1529 100644 --- a/drafts/Data_Visualization.md +++ b/drafts/Data_Visualization.md @@ -1,9 +1,9 @@ # Data Visualization -[Data Visualization Software - Tulip]( http://tulip.labri.fr/TulipDrupal/ ) +[Data Visualization Software - Tulip]( https://tulip.labri.fr/TulipDrupal/ ) -[Data Visualization Techniques – VisualizationSoftware.com]( http://www.visualizationsoftware.com/ ) +[Data Visualization Techniques – VisualizationSoftware.com]( https://www.visualizationsoftware.com/ ) -[Data Visualization Tools]( http://www.data-visualization-tools.com/ ) +[Data Visualization Tools]( https://www.data-visualization-tools.com/ ) -[Data visualization (Wikipedia)]( http://en.wikipedia.org/wiki/Data_visualization ) \ No newline at end of file +[Data visualization (Wikipedia)]( https://en.wikipedia.org/wiki/Data_visualization ) diff --git a/drafts/Java.md b/drafts/Java.md index 54cce3a..bc205c1 100644 --- a/drafts/Java.md +++ b/drafts/Java.md @@ -1,9 +1,5 @@ # Java -[Spock]( http://spockframework.org/ ) +[Spock]( https://spockframework.org/ ) [YourKit - Profiling and Monitoring Tools for Java and .NET Professionals]( https://www.yourkit.com/ ) - - - - diff --git a/drafts/Kong.md b/drafts/Kong.md index f1b8ef8..d0c82c2 100644 --- a/drafts/Kong.md +++ b/drafts/Kong.md @@ -1,3 +1,3 @@ -## Kong +# Kong -[ Kong Summit- Building the Next Era of Software ]( https://konghq.com/kong-summit ) +[Kong Summit- Building the Next Era of Software]( https://konghq.com/kong-summit ) diff --git a/drafts/Logging.md b/drafts/Logging.md index fe3af30..20dcfd5 100644 --- a/drafts/Logging.md +++ b/drafts/Logging.md @@ -1,4 +1,4 @@ -## Log shipping +# Log shipping -[Fluentd]( https://docs.fluentd.org/ ) \ No newline at end of file +[Fluentd]( https://docs.fluentd.org/ ) diff --git a/drafts/Play_Framework2.md b/drafts/Play_Framework2.md index b67b4b3..4c36657 100644 --- a/drafts/Play_Framework2.md +++ b/drafts/Play_Framework2.md @@ -1,19 +1,19 @@ ## Play -[ Angular 2+ with Play Framework 2.6.x – Yohan Gomez – Medium ]( https://medium.com/@yohan.gz/https-medium-com-yohan-gz-angular-with-play-framework-a6c3f8b339f3 ) +[Angular 2+ with Play Framework 2.6.x – Yohan Gomez – Medium]( https://medium.com/@yohan.gz/https-medium-com-yohan-gz-angular-with-play-framework-a6c3f8b339f3 ) -[ yohangz-scala-play-angular-seed- Scala Play 2.6.x + Angular 5 with Angular CLI seed project with full-fledged build process ]( https://github.com/yohangz/scala-play-angular-seed ) +[yohangz-scala-play-angular-seed- Scala Play 2.6.x + Angular 5 with Angular CLI seed project with full-fledged build process]( https://github.com/yohangz/scala-play-angular-seed ) -[ Getting Started With Play Framework - DZone - Refcardz ]( https://dzone.com/refcardz/getting-started-play-framework?chapter=10 ) +[Getting Started With Play Framework - DZone - Refcardz]( https://dzone.com/refcardz/getting-started-play-framework?chapter=10 ) -[ How Visier Accelerates Developer Productivity with Play Framework, Typescript and Angular 2 - @lightbend ]( https://www.lightbend.com/blog/getting-started-with-angular-2 ) +[How Visier Accelerates Developer Productivity with Play Framework, Typescript and Angular 2 - @lightbend]( https://www.lightbend.com/blog/getting-started-with-angular-2 ) -[ jamesward-play-rest-security ]( https://github.com/jamesward/p -lay-rest-security ) +[jamesward-play-rest-security]( https://github.com/jamesward/p +lay-rest-security ) -[ joost-de-vries-play-angular-typescript.g8- A giter8 template for a Play Angular 4 Typescript application ]( https://github.com/joost-de-vries/play-angular-typescript.g8 ) +[joost-de-vries-play-angular-typescript.g8- A giter8 template for a Play Angular 4 Typescript application]( https://github.com/joost-de-vries/play-angular-typescript.g8 ) -[ play-angular-typescript.g8-app.module.ts at master · joost-de-vries-play-angular-typescript.g8 ]( https://github.com/joost-de-vries/play-angular-typescript.g8/blob/master/src/main/g8/app/assets/app/app.module.ts ) +[play-angular-typescript.g8-app.module.ts at master · joost-de-vries-play-angular-typescript.g8]( https://github.com/joost-de-vries/play-angular-typescript.g8/blob/master/src/main/g8/app/assets/app/app.module.ts ) -[ playframework-play-scala-secure-session-example- An example Play application showing encrypted session management ]( https://github.com/playframework/play-scala-secure-session-example ) +[playframework-play-scala-secure-session-example- An example Play application showing encrypted session management]( https://github.com/playframework/play-scala-secure-session-example ) diff --git a/drafts/Scala3.md b/drafts/Scala3.md index 3d62067..c7f1b1b 100644 --- a/drafts/Scala3.md +++ b/drafts/Scala3.md @@ -1,8 +1,8 @@ -## Scala Basics +# Scala Basics -[ Scala Exercises ]( https://www.scala-exercises.org/ ) +[Scala Exercises]( https://www.scala-exercises.org/ ) ## Scala Documentation -[ sbt-microsites- Getting Started ]( https://47deg.github.io/sbt-microsites/docs/ ) +[sbt-microsites- Getting Started]( https://47deg.github.io/sbt-microsites/docs/ ) diff --git a/drafts/Stream_Processing.md b/drafts/Stream_Processing.md index b780075..bcd57fd 100644 --- a/drafts/Stream_Processing.md +++ b/drafts/Stream_Processing.md @@ -1,4 +1,3 @@ # Real-time stream processing -[FASTDATA.io]( https://www.fastdata.io/#fast-data-true-real-time-stream-processing ) - +[FASTDATA.io]( https://www.fastdata.io/#fast-data-true-real-time-stream-processing ) diff --git a/drafts/Terraform2.md b/drafts/Terraform2.md index 04aed7b..bf8737b 100644 --- a/drafts/Terraform2.md +++ b/drafts/Terraform2.md @@ -1,7 +1,6 @@ -## Terraform +# Terraform -[jonmorehouse-terraform-provisioner-ansible- A provisioner for bootstrapping terraform resources with ansible]( https://github.com/jonmorehouse/terraform-provisioner-ansible ) - -[Kubernetes on AWS with Terraform (kubespray)]( https://github.com/kubernetes-incubator/kubespray/tree/master/contrib/terraform/aws ) +[jonmorehouse-terraform-provisioner-ansible- A provisioner for bootstrapping terraform resources with ansible]( https://github.com/jonmorehouse/terraform-provisioner-ansible ) +[Kubernetes on AWS with Terraform (kubespray)]( https://github.com/kubernetes-incubator/kubespray/tree/master/contrib/terraform/aws ) diff --git a/drafts/Windows_Tools.md b/drafts/Windows_Tools.md index 26da0fc..5f8dc7e 100644 --- a/drafts/Windows_Tools.md +++ b/drafts/Windows_Tools.md @@ -1,4 +1 @@ - - - [7 Free Alternatives to Fences for Windows Desktop Management]( https://www.makeuseof.com/tag/windows-desktop-management/ ) diff --git a/mkdocs.yml b/mkdocs.yml index c8c219b..7a83d10 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,54 +1,139 @@ + +## References: +## https://www.mkdocs.org/ +## https://squidfunk.github.io/mkdocs-material/ + # Project information site_name: "John's Cheatsheets" -site_description: 'A collection of cheatsheets and code snippets.' -site_author: 'S. John Cruchon-Dupeyrat' -site_url: 'http://john-cd.com/cheatsheets/' +site_description: "A collection of cheatsheets and code snippets." +site_author: "S. John CD" +site_url: "https://john-cd.com/cheatsheets/" + +# Required within Dev Container (default binding is 127.0.0.1:8000) +dev_addr: 0.0.0.0:8000 + +## Navigation is automatic but can be overriden: +# nav: +# - Home: index.md + +## Strict validation, if required: +# validation: +# omitted_files: warn +# absolute_links: warn +# unrecognized_links: warn # Repository -repo_name: 'john-cd/cheatsheets' -repo_url: 'https://github.com/john-cd/cheatsheets' -edit_uri: edit/master/docs_src/ +repo_name: "john-cd/cheatsheets" +repo_url: "https://github.com/john-cd/cheatsheets" +# automatic: edit_uri: edit/master/docs/ # Copyright -copyright: 'Copyright © 2017-2021 S. John Cruchon-Dupeyrat' - -# Documentation sources and theme -docs_dir: 'docs_src' -site_dir: 'docs' +copyright: > + Copyright © 2016 - 2024 S. John CD – + Change cookie settings theme: - name: material + name: material + + language: en + + #logo: assets/logo.png + #favicon: images/favicon.png + + icon: + repo: fontawesome/brands/github + palette: - primary: deep orange - accent: orange + # Palette toggle for automatic mode + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to system preference + ## Optional color override + # primary: deep orange + # accent: orange font: text: Roboto - code: Roboto Mono + code: Roboto Mono features: -# - navigation.tabs + - navigation.instant + - navigation.instant.progress + - navigation.tracking + # alternative: - navigation.tabs + - navigation.sections + - navigation.prune + - navigation.indexes + - navigation.footer + - toc.integrate + - navigation.top + - search.suggest + - search.highlight + - search.share - header.autohide # Options extra: + consent: + title: Cookie consent + description: >- + We use cookies to recognize your repeated visits and preferences, as well + as to measure the effectiveness of our documentation and whether users + find what they're searching for. With your consent, you're helping us to + make our documentation better. + social: - icon: fontawesome/brands/github - link: 'https://github.com/john-cd' + link: "https://github.com/john-cd" - icon: fontawesome/brands/twitter - link: 'https://twitter.com/sjncd' + link: "https://twitter.com/sjncd" - icon: fontawesome/brands/linkedin - link: 'https://www.linkedin.com/in/scdupeyrat/' -# disqus: 'your-shortname' + link: "https://www.linkedin.com/in/scdupeyrat/" + # disqus: 'your-shortname' + + # Google Analytics + analytics: + provider: google + property: G-VH46N7PJC6 -# Google Analytics -google_analytics: - - 'UA-92780605-1' - - 'auto' + # feedback: + # title: Was this page helpful? + # ratings: + # - icon: material/emoticon-happy-outline + # name: This page was helpful + # data: 1 + # note: >- + # Thanks for your feedback! + # - icon: material/emoticon-sad-outline + # name: This page could be improved + # data: 0 + # note: >- + # Thanks for your feedback! Help us improve this page by + # using our feedback form. # Extensions markdown_extensions: - admonition - - codehilite: - guess_lang: false + - tables - toc: permalink: true - slugify: !!python/name:pymdownx.slugs.uslugify \ No newline at end of file + slugify: !!python/object/apply:pymdownx.slugs.slugify + kwds: + case: lower + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.superfences + - pymdownx.inlinehilite