diff --git a/404.html b/404.html index 17260b12..7204d811 100644 --- a/404.html +++ b/404.html @@ -4,13 +4,13 @@ Page Not Found | DevOps with Docker - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - + + \ No newline at end of file diff --git a/assets/js/06d0a36c.2ff96edf.js b/assets/js/06d0a36c.fe670e4a.js similarity index 60% rename from assets/js/06d0a36c.2ff96edf.js rename to assets/js/06d0a36c.fe670e4a.js index 1b4a5c20..ced06be3 100644 --- a/assets/js/06d0a36c.2ff96edf.js +++ b/assets/js/06d0a36c.fe670e4a.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[366],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>u});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=a.createContext({}),l=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=l(e.components);return a.createElement(p.Provider,{value:t},e.children)},m="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,p=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),m=l(n),h=o,u=m["".concat(p,".").concat(h)]||m[h]||c[h]||r;return n?a.createElement(u,i(i({ref:t},d),{},{components:n})):a.createElement(u,i({ref:t},d))}));function u(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=h;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[m]="string"==typeof e?e:o,i[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var a=n(7462),o=(n(7294),n(3905));const r={title:"Volumes in action"},i=void 0,s={unversionedId:"part-2/section-3",id:"part-2/section-3",title:"Volumes in action",description:"Next we're going to set up the project management application Redmine, a PostgreSQL database and Adminer, a graphical interface for database administration.",source:"@site/docs/part-2/section-3.md",sourceDirName:"part-2",slug:"/part-2/section-3",permalink:"/part-2/section-3",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/part-2/section-3.md",tags:[],version:"current",frontMatter:{title:"Volumes in action"},sidebar:"materialSidebar",previous:{title:"Docker networking",permalink:"/part-2/section-2"},next:{title:"Containers in development",permalink:"/part-2/section-4"}},p={},l=[{value:"Exercises 2.6 - 2.10",id:"exercises-26---210",level:2}],d={toc:l},m="wrapper";function c(e){let{components:t,...r}=e;return(0,o.kt)(m,(0,a.Z)({},d,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Next we're going to set up the project management application ",(0,o.kt)("a",{parentName:"p",href:"https://www.redmine.org/"},"Redmine"),", a PostgreSQL database and ",(0,o.kt)("a",{parentName:"p",href:"https://www.adminer.org/"},"Adminer"),", a graphical interface for database administration."),(0,o.kt)("p",null,"All of the above have official Docker images available as we can see from ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"Redmine"),", ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres"},"Postgres")," and ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/adminer"},"Adminer")," respectively. The officiality of the containers is not that important, just that we can expect that it will have some support. We could also, for example, setup Wordpress or a MediaWiki inside containers in the same manner if you're interested in running existing applications inside Docker. You could even set up an application monitoring tool such as ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/sentry/"},"Sentry"),"."),(0,o.kt)("p",null,"In ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"https://hub.docker.com/_/redmine")," there is a list of different tagged versions:"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Redmine",src:n(9594).Z,width:"1558",height:"464"})),(0,o.kt)("p",null,"We can most likely use any of the available images."),(0,o.kt)("p",null,"From the section ",(0,o.kt)("em",{parentName:"p"},"Environment Variables")," we can see that all versions can use ",(0,o.kt)("inlineCode",{parentName:"p"},"REDMINE_DB_POSTGRES")," environment variable to set up a Postgres database. So before moving forward, let's setup Postgres for us."),(0,o.kt)("p",null,"In ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres"},"https://hub.docker.com/_/postgres")," there's a sample compose file under the section \"via docker-compose or docker stack deploy\". Let's strip that down as follows"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n')),(0,o.kt)("p",null,"Note:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"restart: always")," was changed to ",(0,o.kt)("inlineCode",{parentName:"li"},"unless-stopped"),", that will keep the container running unless we explicitly stop it. With ",(0,o.kt)("inlineCode",{parentName:"li"},"always")," the stopped container is started after reboot, for example, see ",(0,o.kt)("a",{parentName:"li",href:"https://docs.docker.com/config/containers/start-containers-automatically/"},"here")," for more.")),(0,o.kt)("p",null,"Under the section ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/docs/blob/master/postgres/README.md#where-to-store-data"},"Where to store data"),", we can see that the ",(0,o.kt)("inlineCode",{parentName:"p"},"/var/lib/postgresql/data")," should be mounted separately to preserve the data."),(0,o.kt)("p",null,"There are two options for doing the mounting. We could use a bind mount like previously and mount an easy-to-locate directory for storing the data. Let us now use the other option, a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/storage/volumes/"},"Docker managed volume"),"."),(0,o.kt)("p",null,"Let's run the Docker Compose file without setting anything new:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},'$ docker compose up\n\n \u2714 Network redmine_default Created 0.0s\n \u2714 Container db_redmine Created 0.2s\n Attaching to db_redmine\n db_redmine | The files belonging to this database system will be owned by user "postgres".\n db_redmine | This user must also own the server process.\n ...\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: starting PostgreSQL 13.2 on aarch64-unknown-linux-musl, compiled by gcc (Alpine 10.2.1_pre1) 10.2.1 20201203, 64-bit\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: listening on IPv6 address "::", port 5432\n db_redmine | 2024-03-11 14:05:52.342 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"\n db_redmine | 2024-03-11 14:05:52.345 UTC [46] LOG: database system was shut down at 2024-03-11 14:05:52 UTC\n db_redmine | 2024-03-11 14:05:52.347 UTC [1] LOG: database system is ready to accept connections\n')),(0,o.kt)("p",null,"The image initializes the data files in the first start. Let's terminate the container with ^C. Compose uses the current directory as a prefix for container and volume names so that different projects don't clash (The prefix can be overridden with ",(0,o.kt)("inlineCode",{parentName:"p"},"COMPOSE_PROJECT_NAME")," environment variable if needed)."),(0,o.kt)("p",null,"Let's ",(0,o.kt)("strong",{parentName:"p"},"inspect")," if there was a volume created with ",(0,o.kt)("inlineCode",{parentName:"p"},"docker container inspect db_redmine | grep -A 5 Mounts")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"Mounts": [\n {\n "Type": "volume",\n "Name": "2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5",\n "Source": "/var/lib/docker/volumes/2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5/_data",\n "Destination": "/var/lib/postgresql/data",\n')),(0,o.kt)("p",null,"An indeed there is one! So despite us ",(0,o.kt)("strong",{parentName:"p"},"not")," configuring one explicitly, an anonymous volume was automatically created for us."),(0,o.kt)("p",null,"Now if we check out ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume ls"),' we can see that a volume with the name "2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5" exists.'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"$ docker volume ls\n DRIVER VOLUME NAME\n local 2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5\n")),(0,o.kt)("p",null,"There may be more volumes on your machine. If you want to get rid of them you can use ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume prune"),'. Let\'s put the whole "application" down now with ',(0,o.kt)("inlineCode",{parentName:"p"},"docker compose down"),"."),(0,o.kt)("p",null,"Instead of the randomly named volume we better define one explicitly.\nLet us change the definition as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n volumes:\n - database:/var/lib/postgresql/data\n\nvolumes:\n database:\n')),(0,o.kt)("p",null,"Now, after running ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," again, let us check what it looks like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},'$ docker volume ls\n DRIVER VOLUME NAME\n local redmine_database\n\n$ docker container inspect db_redmine | grep -A 5 Mounts\n"Mounts": [\n {\n "Type": "volume",\n "Name": "redmine_database",\n "Source": "/var/lib/docker/volumes/ongoing_redminedata/_data",\n "Destination": "/var/lib/postgresql/data",\n')),(0,o.kt)("p",null,"Ok, looks a bit more human-readable! Now when the Postgres is running, it is time to add ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"Redmine"),"."),(0,o.kt)("p",null,"The container seems to require just two environment variables."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"redmine:\n image: redmine:5.1-alpine\n environment:\n - REDMINE_DB_POSTGRES=db\n - REDMINE_DB_PASSWORD=example\n ports:\n - 9999:3000\n depends_on:\n - db\n")),(0,o.kt)("p",null,"Notice the ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on"},"depends_on")," declaration. This makes sure that the ",(0,o.kt)("inlineCode",{parentName:"p"},"db")," service is started first. ",(0,o.kt)("inlineCode",{parentName:"p"},"depends_on"),' does not guarantee that the database is up, just that it is started first. The Postgres server is accessible with the DNS name "db" from the Redmine service as discussed in the section ',(0,o.kt)("a",{parentName:"p",href:"/part-2/section-2"},"Docker networking"),"."),(0,o.kt)("p",null,"Now when you run ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," you will see a bunch of database migrations running first."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"}," redmine_1 | I, [2024-03-03T10:59:20.956936 #25] INFO -- : Migrating to Setup (1)\n redmine_1 | == 1 Setup: migrating =========================================================\n ...\n redmine_1 | [2024-03-03 11:01:10] INFO ruby 3.2.3 (2024-01-30) [x86_64-linux]\n redmine_1 | [2024-03-03 11:01:10] INFO WEBrick::HTTPServer#start: pid=1 port=3000\n")),(0,o.kt)("p",null,"As the ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"documentation")," mentions, the image creates files to ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/src/redmine/files")," and those are better to be persisted. The Dockerfile has this ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/redmine/blob/cea16044e97567c28802fc8cc06f6cd036c49a5c/4.0/Dockerfile#L155"},"line")," where it declares that a volume should be created. Again Docker will create the volume, but it will be handled as an anonymous volume that is not managed by the Docker Compose, so it's better to create it explicitly."),(0,o.kt)("p",null,"With that in mind, our configuration changes to this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n volumes:\n - database:/var/lib/postgresql/data\n redmine:\n image: redmine:4.1-alpine\n environment:\n - REDMINE_DB_POSTGRES=db\n - REDMINE_DB_PASSWORD=example\n ports:\n - 9999:3000\n volumes:\n - files:/usr/src/redmine/files\n depends_on:\n - db\n\nvolumes:\n database:\n files:\n')),(0,o.kt)("p",null,"Now we can use the application with our browser through ",(0,o.kt)("a",{parentName:"p",href:"http://localhost:9999"},"http://localhost:9999"),". After some changes inside the application, we can inspect the changes that happened in the image and check that no extra meaningful files got written to the container:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"$ docker container diff $(docker compose ps -q redmine)\n C /usr/src/redmine/config/environment.rb\n ...\n C /usr/src/redmine/tmp/pdf\n")),(0,o.kt)("p",null,"Probably not."),(0,o.kt)("p",null,"We could use command ",(0,o.kt)("inlineCode",{parentName:"p"},"psql")," inside the Postgres container to interact with the database by running"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"docker container exec -it db_redmine psql -U postgres\n")),(0,o.kt)("p",null,"The same method can be used to create backups with pg_dump"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"docker container exec db_redmine pg_dump -U postgres > redmine.dump\n")),(0,o.kt)("p",null,"Rather than using the archaic command line interface to access Postgres, let us now set up the database ",(0,o.kt)("a",{parentName:"p",href:"https://www.adminer.org/"},"Adminer")," to the application."),(0,o.kt)("p",null,"After a look at the ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/adminer"},"documentation"),", the setup is straightforward:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"adminer:\n image: adminer:4\n restart: always\n environment:\n - ADMINER_DESIGN=galkaev\n ports:\n - 8083:8080\n")),(0,o.kt)("p",null,"Now when we run the application we can access the adminer from ",(0,o.kt)("a",{parentName:"p",href:"http://localhost:8083"},"http://localhost:8083"),":"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Adminer view",src:n(6715).Z,width:"1892",height:"730"})),(0,o.kt)("p",null,"Setting up the adminer is straightforward since it will be able to access the database through the Docker network. You may wonder how the adminer finds the Postgres database container. We provide this information to Redmine using an environment variable:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"}," redmine:\n environment:\n - REDMINE_DB_POSTGRES=db\n")),(0,o.kt)("p",null,"Adminer actually assumes that the database has DNS name ",(0,o.kt)("em",{parentName:"p"},"db")," so with this name selection, we did not have to specify anything. If the database has some other name, we have to pass it to adminer using an environment variable:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"}," adminer:\n environment:\n - ADMINER_DEFAULT_SERVER=database_server\n")),(0,o.kt)("h2",{id:"exercises-26---210"},"Exercises 2.6 - 2.10"),(0,o.kt)("admonition",{title:"Exercise 2.6",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Let us continue with the example app that we worked with in ",(0,o.kt)("a",{parentName:"p",href:"/part-2/section-2#exercise-24"},"Exercise 2.4"),"."),(0,o.kt)("p",{parentName:"admonition"},"Now you should add a database to the example backend."),(0,o.kt)("p",{parentName:"admonition"},"Use a Postgres database to save messages. For now, there is no need to configure a volume since the official Postgres image sets a default volume for us. Use the Postgres image documentation to your advantage when configuring: ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres/"},"https://hub.docker.com/","_","/postgres/"),". Especially part ",(0,o.kt)("em",{parentName:"p"},"Environment Variables")," is a valuable one."),(0,o.kt)("p",{parentName:"admonition"},"The backend ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-backend"},"README")," should have all the information needed to\nconnect."),(0,o.kt)("p",{parentName:"admonition"},"There is again a button (and a form!) in the frontend that you can use to ensure your configuration is done right."),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TIP: When configuring the database, you might need to destroy the automatically created volumes. Use commands ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume prune"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume ls")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume rm")," to remove unused volumes when testing. Make sure to remove containers that depend on them beforehand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"restart: unless-stopped")," can help if the Postgres takes a while to get ready"))),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("img",{alt:"Backend, frontend, redis and a database",src:n(7389).Z,width:"713",height:"291"}))),(0,o.kt)("admonition",{title:"Exercise 2.7",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Postgres image uses a volume by default. Define manually a volume for the database in a convenient location such as in ",(0,o.kt)("inlineCode",{parentName:"p"},"./database")," so you should use now a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/storage/bind-mounts/"},"bind mount"),". The image ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/docs/blob/master/postgres/README.md#where-to-store-data"},"documentation")," may help you with the task."),(0,o.kt)("p",{parentName:"admonition"},"After you have configured the bind mount volume:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},"Save a few messages through the frontend"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose down")),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose up")," and see that the messages are available after refreshing browser"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose down")," and delete the volume folder manually"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose up")," and the data should be gone")),(0,o.kt)("blockquote",{parentName:"admonition"},(0,o.kt)("p",{parentName:"blockquote"},"TIP: To save you the trouble of testing all of those steps, just look into the folder before trying the steps. If\nit's empty after ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," then something is wrong.")),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml"),(0,o.kt)("p",{parentName:"admonition"},"The benefit of a bind mount is that since you know exactly where the data is in your file system, it is easy to create backups. If the Docker managed volumes are used, the location of the data in the file system can not be controlled and that makes backups a bit less trivial...")),(0,o.kt)("admonition",{title:"Tips for making sure the backend connection works",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"In the next exercise try using your browser to access http://localhost/api/ping and see if it answers pong"),(0,o.kt)("p",{parentName:"admonition"},"It might be Nginx configuration problem. Ensure there is a trailing / on the backend URL as specified under the location /api/ context in the nginx.conf.")),(0,o.kt)("admonition",{title:"Exercise 2.8",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Add ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/nginx"},"Nginx")," to the example to work as a ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Reverse_proxy"},"reverse proxy")," in front of the example app frontend and backend. According to Wikipedia"),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("em",{parentName:"p"},"A reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client, appearing as if they originated from the reverse proxy server itself.")),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("img",{alt:"Backend, frontend, redis, a database and nginx",src:n(9462).Z,width:"646",height:"331"})),(0,o.kt)("p",{parentName:"admonition"},"So in our case, the reverse proxy will be the single point of entry to our application, and the final goal will be to set both the React frontend and the Express backend behind the reverse proxy."),(0,o.kt)("p",{parentName:"admonition"},"The idea is that a browser makes ",(0,o.kt)("em",{parentName:"p"},"all")," requests to ",(0,o.kt)("em",{parentName:"p"},"http://localhost"),". If the request has a URL prefix ",(0,o.kt)("em",{parentName:"p"},"http://localhost/api"),", Nginx should forward the request to the backend container. All the other requests are directed to the frontend container."),(0,o.kt)("p",{parentName:"admonition"},"So, at the end, you should see that the frontend is accessible simply by going to ",(0,o.kt)("a",{parentName:"p",href:"http://localhost"},"http://localhost"),". All buttons, except the one labeled ",(0,o.kt)("em",{parentName:"p"},"Exercise 2.8")," may have stopped working, do not worry about them, we shall fix that later."),(0,o.kt)("p",{parentName:"admonition"},"The following file should be set to ",(0,o.kt)("em",{parentName:"p"},"/etc/nginx/nginx.conf")," inside the nginx container. You can use a file bind mount where the contents of the file is the following:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"events { worker_connections 1024; }\n\nhttp {\n server {\n listen 80;\n\n location / {\n proxy_pass _frontend-connection-url_;\n }\n\n # configure here where requests to http://localhost/api/...\n # are forwarded\n location /api/ {\n proxy_set_header Host $host;\n proxy_pass _backend-connection-url_;\n }\n }\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"Nginx, backend and frontend should be connected in the same network. See the image above for how the services are connected. You find ",(0,o.kt)("a",{parentName:"p",href:"https://www.nginx.com/resources/wiki/start/topics/examples/full/"},"Nginx-documentation")," helpful, but remember, the configuration you need is pretty straightforward, if you end up doing complex things, you are most likely doing something wrong."),(0,o.kt)("p",{parentName:"admonition"},'If and when your app "does not work", remember to have a look in the log, it can be pretty helpful in pinpointing errors:'),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"2_7-proxy-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh\n2_7-proxy-1 | /docker-entrypoint.sh: Configuration complete; ready for start up\n2_7-proxy-1 | 2023/03/05 09:24:51 [emerg] 1#1: invalid URL prefix in /etc/nginx/nginx.conf:8\n2_7-proxy-1 exited with code 1\n")),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml")),(0,o.kt)("admonition",{title:"Exercise 2.9",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Most of the buttons may have stopped working in the example application. Make sure that every button for exercises works."),(0,o.kt)("p",{parentName:"admonition"},"Remember to take a peek into the browser's developer consoles again like we did back ",(0,o.kt)("a",{parentName:"p",href:"/part-1/section-6"},"part 1"),", remember also ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-frontend#exercise-114---to-connect-to-backend"},"this")," and ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-backend"},"this"),"."),(0,o.kt)("p",{parentName:"admonition"},"The buttons of the Nginx exercise and the first button behave differently but you want them to match."),(0,o.kt)("p",{parentName:"admonition"},"If you had to make any changes explain what you did and where."),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml and both Dockerfiles.")),(0,o.kt)("admonition",{title:"Publishing ports to host network",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"There is an important lesson about Docker networking and ports to be learned in the next exercise."),(0,o.kt)("p",{parentName:"admonition"},"When we do a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/desktop/networking/#port-mapping"},"port mapping"),", in ",(0,o.kt)("inlineCode",{parentName:"p"},"docker run -p 8001:80 ...")," or in the Docker Compose file, we ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/config/containers/container-networking/#published-ports"},"publish")," a container port to the host network to be accessible in localhost."),(0,o.kt)("p",{parentName:"admonition"},"The container port is there within the Docker network accessible by the other containers that are in the same network even if we do not publish anything. So publishing the ports is only for exposing ports outside the Docker network. If no direct access outside the network is not needed, then we just do not publish anything.")),(0,o.kt)("admonition",{title:"Exercise 2.10",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Now we have the reverse proxy up and running! All the communication to our app should be done through the reverse proxy and direct access (eg. accessing the backend with a GET to http://localhost:8080/ping ) should be prevented."),(0,o.kt)("p",{parentName:"admonition"},"Use a port scanner, eg ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/r/networkstatic/nmap"},"https://hub.docker.com/r/networkstatic/nmap")," to ensure that there are no extra ports open in the host."),(0,o.kt)("p",{parentName:"admonition"},"It might be enough to just run"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"$ docker run -it --rm --network host networkstatic/nmap localhost\n")),(0,o.kt)("p",{parentName:"admonition"},"If you have an M1/M2 Mac, you might need to build the image yourself."),(0,o.kt)("p",{parentName:"admonition"},"The result looks like the following (I used a self-built image):"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ docker run -it --rm --network host nmap localhost\nStarting Nmap 7.93 ( https://nmap.org ) at 2023-03-05 12:28 UTC\nNmap scan report for localhost (127.0.0.1)\nHost is up (0.0000040s latency).\nOther addresses for localhost (not scanned): ::1\nNot shown: 996 closed tcp ports (reset)\nPORT STATE SERVICE\n80/tcp filtered http\n111/tcp open rpcbind\n5000/tcp filtered commplex-link\n8080/tcp filtered http-proxy\n\nNmap done: 1 IP address (1 host up) scanned in 1.28 seconds\n")),(0,o.kt)("p",{parentName:"admonition"},"As we see, there are two suspicious open ports: 5000 and 8080. So it is obvious that the frontend and backend are still directly accessible in the host network. This should be fixed!"),(0,o.kt)("p",{parentName:"admonition"},"You are done when the port scan report looks something like this:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-05 12:39 UTC\nNmap scan report for localhost (127.0.0.1)\nHost is up (0.0000040s latency).\nOther addresses for localhost (not scanned): ::1\nNot shown: 998 closed tcp ports (reset)\nPORT STATE SERVICE\n80/tcp filtered http\n111/tcp open rpcbind\n\nNmap done: 1 IP address (1 host up) scanned in 1.28 seconds\n"))))}c.isMDXComponent=!0},6715:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/adminer-fea0b2f85933608d9bba6981eeb033c7.png"},9594:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/redmine2024-c58915fec1682f9c84e2ba48332a3f85.png"},7389:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/back-front-redis-and-database-5aaf7f70f4e7f9f0873e2be9710ea5e6.png"},9462:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/back-front-redis-database-and-nginx-6cf5c082483c2a445501cafe19017fbc.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[366],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>u});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=a.createContext({}),l=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=l(e.components);return a.createElement(p.Provider,{value:t},e.children)},m="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,p=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),m=l(n),h=o,u=m["".concat(p,".").concat(h)]||m[h]||c[h]||r;return n?a.createElement(u,i(i({ref:t},d),{},{components:n})):a.createElement(u,i({ref:t},d))}));function u(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=h;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[m]="string"==typeof e?e:o,i[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var a=n(7462),o=(n(7294),n(3905));const r={title:"Volumes in action"},i=void 0,s={unversionedId:"part-2/section-3",id:"part-2/section-3",title:"Volumes in action",description:"Next we're going to set up the project management application Redmine, a PostgreSQL database and Adminer, a graphical interface for database administration.",source:"@site/docs/part-2/section-3.md",sourceDirName:"part-2",slug:"/part-2/section-3",permalink:"/part-2/section-3",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/part-2/section-3.md",tags:[],version:"current",frontMatter:{title:"Volumes in action"},sidebar:"materialSidebar",previous:{title:"Docker networking",permalink:"/part-2/section-2"},next:{title:"Containers in development",permalink:"/part-2/section-4"}},p={},l=[{value:"Exercises 2.6 - 2.10",id:"exercises-26---210",level:2}],d={toc:l},m="wrapper";function c(e){let{components:t,...r}=e;return(0,o.kt)(m,(0,a.Z)({},d,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Next we're going to set up the project management application ",(0,o.kt)("a",{parentName:"p",href:"https://www.redmine.org/"},"Redmine"),", a PostgreSQL database and ",(0,o.kt)("a",{parentName:"p",href:"https://www.adminer.org/"},"Adminer"),", a graphical interface for database administration."),(0,o.kt)("p",null,"All of the above have official Docker images available as we can see from ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"Redmine"),", ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres"},"Postgres")," and ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/adminer"},"Adminer")," respectively. The officiality of the containers is not that important, just that we can expect that it will have some support. We could also, for example, setup Wordpress or a MediaWiki inside containers in the same manner if you're interested in running existing applications inside Docker. You could even set up an application monitoring tool such as ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/sentry/"},"Sentry"),"."),(0,o.kt)("p",null,"In ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"https://hub.docker.com/_/redmine")," there is a list of different tagged versions:"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Redmine",src:n(9594).Z,width:"1558",height:"464"})),(0,o.kt)("p",null,"We can most likely use any of the available images."),(0,o.kt)("p",null,"From the section ",(0,o.kt)("em",{parentName:"p"},"Environment Variables")," we can see that all versions can use ",(0,o.kt)("inlineCode",{parentName:"p"},"REDMINE_DB_POSTGRES")," environment variable to set up a Postgres database. So before moving forward, let's setup Postgres for us."),(0,o.kt)("p",null,"In ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres"},"https://hub.docker.com/_/postgres")," there's a sample compose file under the section \"via docker-compose or docker stack deploy\". Let's strip that down as follows"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n')),(0,o.kt)("p",null,"Note:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"restart: always")," was changed to ",(0,o.kt)("inlineCode",{parentName:"li"},"unless-stopped"),", that will keep the container running unless we explicitly stop it. With ",(0,o.kt)("inlineCode",{parentName:"li"},"always")," the stopped container is started after reboot, for example, see ",(0,o.kt)("a",{parentName:"li",href:"https://docs.docker.com/config/containers/start-containers-automatically/"},"here")," for more.")),(0,o.kt)("p",null,"Under the section ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/docs/blob/master/postgres/README.md#where-to-store-data"},"Where to store data"),", we can see that the ",(0,o.kt)("inlineCode",{parentName:"p"},"/var/lib/postgresql/data")," should be mounted separately to preserve the data."),(0,o.kt)("p",null,"There are two options for doing the mounting. We could use a bind mount like previously and mount an easy-to-locate directory for storing the data. Let us now use the other option, a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/storage/volumes/"},"Docker managed volume"),"."),(0,o.kt)("p",null,"Let's run the Docker Compose file without setting anything new:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},'$ docker compose up\n\n \u2714 Network redmine_default Created 0.0s\n \u2714 Container db_redmine Created 0.2s\n Attaching to db_redmine\n db_redmine | The files belonging to this database system will be owned by user "postgres".\n db_redmine | This user must also own the server process.\n ...\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: starting PostgreSQL 13.2 on aarch64-unknown-linux-musl, compiled by gcc (Alpine 10.2.1_pre1) 10.2.1 20201203, 64-bit\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432\n db_redmine | 2024-03-11 14:05:52.340 UTC [1] LOG: listening on IPv6 address "::", port 5432\n db_redmine | 2024-03-11 14:05:52.342 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"\n db_redmine | 2024-03-11 14:05:52.345 UTC [46] LOG: database system was shut down at 2024-03-11 14:05:52 UTC\n db_redmine | 2024-03-11 14:05:52.347 UTC [1] LOG: database system is ready to accept connections\n')),(0,o.kt)("p",null,"The image initializes the data files in the first start. Let's terminate the container with ^C. Compose uses the current directory as a prefix for container and volume names so that different projects don't clash (The prefix can be overridden with ",(0,o.kt)("inlineCode",{parentName:"p"},"COMPOSE_PROJECT_NAME")," environment variable if needed)."),(0,o.kt)("p",null,"Let's ",(0,o.kt)("strong",{parentName:"p"},"inspect")," if there was a volume created with ",(0,o.kt)("inlineCode",{parentName:"p"},"docker container inspect db_redmine | grep -A 5 Mounts")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"Mounts": [\n {\n "Type": "volume",\n "Name": "2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5",\n "Source": "/var/lib/docker/volumes/2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5/_data",\n "Destination": "/var/lib/postgresql/data",\n')),(0,o.kt)("p",null,"An indeed there is one! So despite us ",(0,o.kt)("strong",{parentName:"p"},"not")," configuring one explicitly, an anonymous volume was automatically created for us."),(0,o.kt)("p",null,"Now if we check out ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume ls"),' we can see that a volume with the name "2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5" exists.'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"$ docker volume ls\n DRIVER VOLUME NAME\n local 2d86a2480b60743147ce88e8e70b612d10b4c4151779b462baf4e81b84061ef5\n")),(0,o.kt)("p",null,"There may be more volumes on your machine. If you want to get rid of them you can use ",(0,o.kt)("inlineCode",{parentName:"p"},"docker volume prune"),'. Let\'s put the whole "application" down now with ',(0,o.kt)("inlineCode",{parentName:"p"},"docker compose down"),"."),(0,o.kt)("p",null,"Instead of the randomly named volume we better define one explicitly.\nLet us change the definition as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n volumes:\n - database:/var/lib/postgresql/data\n\nvolumes:\n database:\n')),(0,o.kt)("p",null,"Now, after running ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," again, let us check what it looks like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},'$ docker volume ls\n DRIVER VOLUME NAME\n local redmine_database\n\n$ docker container inspect db_redmine | grep -A 5 Mounts\n"Mounts": [\n {\n "Type": "volume",\n "Name": "redmine_database",\n "Source": "/var/lib/docker/volumes/ongoing_redminedata/_data",\n "Destination": "/var/lib/postgresql/data",\n')),(0,o.kt)("p",null,"Ok, looks a bit more human-readable! Now when the Postgres is running, it is time to add ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"Redmine"),"."),(0,o.kt)("p",null,"The container seems to require just two environment variables."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"redmine:\n image: redmine:5.1-alpine\n environment:\n - REDMINE_DB_POSTGRES=db\n - REDMINE_DB_PASSWORD=example\n ports:\n - 9999:3000\n depends_on:\n - db\n")),(0,o.kt)("p",null,"Notice the ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on"},"depends_on")," declaration. This makes sure that the ",(0,o.kt)("inlineCode",{parentName:"p"},"db")," service is started first. ",(0,o.kt)("inlineCode",{parentName:"p"},"depends_on"),' does not guarantee that the database is up, just that it is started first. The Postgres server is accessible with the DNS name "db" from the Redmine service as discussed in the section ',(0,o.kt)("a",{parentName:"p",href:"/part-2/section-2"},"Docker networking"),"."),(0,o.kt)("p",null,"Now when you run ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," you will see a bunch of database migrations running first."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"}," redmine_1 | I, [2024-03-03T10:59:20.956936 #25] INFO -- : Migrating to Setup (1)\n redmine_1 | == 1 Setup: migrating =========================================================\n ...\n redmine_1 | [2024-03-03 11:01:10] INFO ruby 3.2.3 (2024-01-30) [x86_64-linux]\n redmine_1 | [2024-03-03 11:01:10] INFO WEBrick::HTTPServer#start: pid=1 port=3000\n")),(0,o.kt)("p",null,"As the ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/redmine"},"documentation")," mentions, the image creates files to ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/src/redmine/files")," and those are better to be persisted. The Dockerfile has this ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/redmine/blob/cea16044e97567c28802fc8cc06f6cd036c49a5c/4.0/Dockerfile#L155"},"line")," where it declares that a volume should be created. Again Docker will create the volume, but it will be handled as an anonymous volume that is not managed by the Docker Compose, so it's better to create it explicitly."),(0,o.kt)("p",null,"With that in mind, our configuration changes to this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'version: "3.8"\n\nservices:\n db:\n image: postgres:13.2-alpine\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: example\n container_name: db_redmine\n volumes:\n - database:/var/lib/postgresql/data\n redmine:\n image: redmine:4.1-alpine\n environment:\n - REDMINE_DB_POSTGRES=db\n - REDMINE_DB_PASSWORD=example\n ports:\n - 9999:3000\n volumes:\n - files:/usr/src/redmine/files\n depends_on:\n - db\n\nvolumes:\n database:\n files:\n')),(0,o.kt)("p",null,"Now we can use the application with our browser through ",(0,o.kt)("a",{parentName:"p",href:"http://localhost:9999"},"http://localhost:9999"),". After some changes inside the application, we can inspect the changes that happened in the image and check that no extra meaningful files got written to the container:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"$ docker container diff $(docker compose ps -q redmine)\n C /usr/src/redmine/config/environment.rb\n ...\n C /usr/src/redmine/tmp/pdf\n")),(0,o.kt)("p",null,"Probably not."),(0,o.kt)("p",null,"We could use command ",(0,o.kt)("inlineCode",{parentName:"p"},"psql")," inside the Postgres container to interact with the database by running"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"docker container exec -it db_redmine psql -U postgres\n")),(0,o.kt)("p",null,"The same method can be used to create backups with pg_dump"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-console"},"docker container exec db_redmine pg_dump -U postgres > redmine.dump\n")),(0,o.kt)("p",null,"Rather than using the archaic command line interface to access Postgres, let us now set up the database ",(0,o.kt)("a",{parentName:"p",href:"https://www.adminer.org/"},"Adminer")," to the application."),(0,o.kt)("p",null,"After a look at the ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/adminer"},"documentation"),", the setup is straightforward:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"adminer:\n image: adminer:4\n restart: always\n environment:\n - ADMINER_DESIGN=galkaev\n ports:\n - 8083:8080\n")),(0,o.kt)("p",null,"Now when we run the application we can access the adminer from ",(0,o.kt)("a",{parentName:"p",href:"http://localhost:8083"},"http://localhost:8083"),":"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Adminer view",src:n(6715).Z,width:"1892",height:"730"})),(0,o.kt)("p",null,"Setting up the adminer is straightforward since it will be able to access the database through the Docker network. You may wonder how the adminer finds the Postgres database container. We provide this information to Redmine using an environment variable:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"}," redmine:\n environment:\n - REDMINE_DB_POSTGRES=db\n")),(0,o.kt)("p",null,"Adminer actually assumes that the database has DNS name ",(0,o.kt)("em",{parentName:"p"},"db")," so with this name selection, we did not have to specify anything. If the database has some other name, we have to pass it to adminer using an environment variable:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"}," adminer:\n environment:\n - ADMINER_DEFAULT_SERVER=database_server\n")),(0,o.kt)("h2",{id:"exercises-26---210"},"Exercises 2.6 - 2.10"),(0,o.kt)("admonition",{title:"Exercise 2.6",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Let us continue with the example app that we worked with in ",(0,o.kt)("a",{parentName:"p",href:"/part-2/section-2#exercise-24"},"Exercise 2.4"),"."),(0,o.kt)("p",{parentName:"admonition"},"Now you should add a database to the example backend."),(0,o.kt)("p",{parentName:"admonition"},"Use a Postgres database to save messages. For now, there is no need to configure a volume since the official Postgres image sets a default volume for us. Use the Postgres image documentation to your advantage when configuring: ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/postgres/"},"https://hub.docker.com/","_","/postgres/"),". Especially part ",(0,o.kt)("em",{parentName:"p"},"Environment Variables")," is a valuable one."),(0,o.kt)("p",{parentName:"admonition"},"The backend ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-backend"},"README")," should have all the information needed to\nconnect."),(0,o.kt)("p",{parentName:"admonition"},"There is again a button (and a form!) in the frontend that you can use to ensure your configuration is done right."),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml"),(0,o.kt)("p",{parentName:"admonition"},"TIPS:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},"When configuring the database, you might need to destroy the automatically created volumes. Use commands ",(0,o.kt)("inlineCode",{parentName:"li"},"docker volume prune"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"docker volume ls")," and ",(0,o.kt)("inlineCode",{parentName:"li"},"docker volume rm")," to remove unused volumes when testing. Make sure to remove containers that depend on them beforehand."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"restart: unless-stopped")," can help if the Postgres takes a while to get ready")),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("img",{alt:"Backend, frontend, redis and a database",src:n(7389).Z,width:"713",height:"291"}))),(0,o.kt)("admonition",{title:"Exercise 2.7",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Postgres image uses a volume by default. Define manually a volume for the database in a convenient location such as in ",(0,o.kt)("inlineCode",{parentName:"p"},"./database")," so you should use now a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/storage/bind-mounts/"},"bind mount"),". The image ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-library/docs/blob/master/postgres/README.md#where-to-store-data"},"documentation")," may help you with the task."),(0,o.kt)("p",{parentName:"admonition"},"After you have configured the bind mount volume:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},"Save a few messages through the frontend"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose down")),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose up")," and see that the messages are available after refreshing browser"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose down")," and delete the volume folder manually"),(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"docker compose up")," and the data should be gone")),(0,o.kt)("blockquote",{parentName:"admonition"},(0,o.kt)("p",{parentName:"blockquote"},"TIP: To save you the trouble of testing all of those steps, just look into the folder before trying the steps. If\nit's empty after ",(0,o.kt)("inlineCode",{parentName:"p"},"docker compose up")," then something is wrong.")),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml"),(0,o.kt)("p",{parentName:"admonition"},"The benefit of a bind mount is that since you know exactly where the data is in your file system, it is easy to create backups. If the Docker managed volumes are used, the location of the data in the file system can not be controlled and that makes backups a bit less trivial...")),(0,o.kt)("admonition",{title:"Tips for making sure the backend connection works",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"In the next exercise try using your browser to access http://localhost/api/ping and see if it answers pong"),(0,o.kt)("p",{parentName:"admonition"},"It might be Nginx configuration problem. Ensure there is a trailing / on the backend URL as specified under the location /api/ context in the nginx.conf.")),(0,o.kt)("admonition",{title:"Exercise 2.8",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"In this exercise, you shall add ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/_/nginx"},"Nginx")," to work as a ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Reverse_proxy"},"reverse proxy")," in front of the example app frontend and backend."),(0,o.kt)("p",{parentName:"admonition"},"According to Wikipedia ",(0,o.kt)("em",{parentName:"p"},"a reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client, appearing as if they originated from the reverse proxy server itself.")),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("img",{alt:"Backend, frontend, redis, a database and nginx",src:n(9462).Z,width:"646",height:"331"})),(0,o.kt)("p",{parentName:"admonition"},"So in our case, the reverse proxy will be the single point of entry to our application, and the final goal will be to set both the React frontend and the Express backend behind the reverse proxy."),(0,o.kt)("p",{parentName:"admonition"},"The idea is that a browser makes ",(0,o.kt)("em",{parentName:"p"},"all")," requests to ",(0,o.kt)("em",{parentName:"p"},"http://localhost"),". If the request has a URL prefix ",(0,o.kt)("em",{parentName:"p"},"http://localhost/api"),", Nginx should forward the request to the backend container. All the other requests are directed to the frontend container."),(0,o.kt)("p",{parentName:"admonition"},"So, at the end, you should see that the frontend is accessible simply by going to ",(0,o.kt)("a",{parentName:"p",href:"http://localhost"},"http://localhost"),". All buttons, except the one labeled ",(0,o.kt)("em",{parentName:"p"},"Exercise 2.8")," may have stopped working, do not worry about them, we shall fix that later."),(0,o.kt)("p",{parentName:"admonition"},"The following file should be set to ",(0,o.kt)("em",{parentName:"p"},"/etc/nginx/nginx.conf")," inside the Nginx container. You can use a file bind mount where the contents of the file is the following:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"events { worker_connections 1024; }\n\nhttp {\n server {\n listen 80;\n\n location / {\n proxy_pass _frontend-connection-url_;\n }\n\n # configure here where requests to http://localhost/api/...\n # are forwarded\n location /api/ {\n proxy_set_header Host $host;\n proxy_pass _backend-connection-url_;\n }\n }\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"Nginx, backend and frontend should be connected in the same network. See the image above for how the services are connected. You find ",(0,o.kt)("a",{parentName:"p",href:"https://www.nginx.com/resources/wiki/start/topics/examples/full/"},"Nginx-documentation")," helpful, but remember, the configuration you need is pretty straightforward, if you end up doing complex things, you are most likely doing something wrong."),(0,o.kt)("p",{parentName:"admonition"},'If and when your app "does not work", remember to have a look in the log, it can be pretty helpful in pinpointing errors:'),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"2_7-proxy-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh\n2_7-proxy-1 | /docker-entrypoint.sh: Configuration complete; ready for start up\n2_7-proxy-1 | 2023/03/05 09:24:51 [emerg] 1#1: invalid URL prefix in /etc/nginx/nginx.conf:8\n2_7-proxy-1 exited with code 1\n")),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml")),(0,o.kt)("admonition",{title:"Exercise 2.9",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Most of the buttons may have stopped working in the example application. Make sure that every button for exercises works."),(0,o.kt)("p",{parentName:"admonition"},"Remember to take a peek into the browser's developer consoles again like we did back ",(0,o.kt)("a",{parentName:"p",href:"/part-1/section-6"},"part 1"),", remember also ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-frontend#exercise-114---to-connect-to-backend"},"this")," and ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/example-backend"},"this"),"."),(0,o.kt)("p",{parentName:"admonition"},"The buttons of the Nginx exercise and the first button behave differently but you want them to match."),(0,o.kt)("p",{parentName:"admonition"},"If you had to make any changes explain what you did and where."),(0,o.kt)("p",{parentName:"admonition"},"Submit the docker-compose.yml and both Dockerfiles.")),(0,o.kt)("admonition",{title:"Publishing ports to host network",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"There is an important lesson about Docker networking and ports to be learned in the next exercise."),(0,o.kt)("p",{parentName:"admonition"},"When we do a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/desktop/networking/#port-mapping"},"port mapping"),", in ",(0,o.kt)("inlineCode",{parentName:"p"},"docker run -p 8001:80 ...")," or in the Docker Compose file, we ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/config/containers/container-networking/#published-ports"},"publish")," a container port to the host network to be accessible in localhost."),(0,o.kt)("p",{parentName:"admonition"},"The container port is there within the Docker network accessible by the other containers that are in the same network even if we do not publish anything. So publishing the ports is only for exposing ports outside the Docker network. If no direct access outside the network is not needed, then we just do not publish anything.")),(0,o.kt)("admonition",{title:"Exercise 2.10",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Now we have the reverse proxy up and running! All the communication to our app should be done through the reverse proxy and direct access (eg. accessing the backend with a GET to http://localhost:8080/ping ) should be prevented."),(0,o.kt)("p",{parentName:"admonition"},"Use a port scanner, eg ",(0,o.kt)("a",{parentName:"p",href:"https://hub.docker.com/r/networkstatic/nmap"},"https://hub.docker.com/r/networkstatic/nmap")," to ensure that there are no extra ports open in the host."),(0,o.kt)("p",{parentName:"admonition"},"It might be enough to just run"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"$ docker run -it --rm --network host networkstatic/nmap localhost\n")),(0,o.kt)("p",{parentName:"admonition"},"If you have an M1/M2 Mac, you might need to build the image yourself."),(0,o.kt)("p",{parentName:"admonition"},"The result looks like the following (I used a self-built image):"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ docker run -it --rm --network host nmap localhost\nStarting Nmap 7.93 ( https://nmap.org ) at 2023-03-05 12:28 UTC\nNmap scan report for localhost (127.0.0.1)\nHost is up (0.0000040s latency).\nOther addresses for localhost (not scanned): ::1\nNot shown: 996 closed tcp ports (reset)\nPORT STATE SERVICE\n80/tcp filtered http\n111/tcp open rpcbind\n5000/tcp filtered commplex-link\n8080/tcp filtered http-proxy\n\nNmap done: 1 IP address (1 host up) scanned in 1.28 seconds\n")),(0,o.kt)("p",{parentName:"admonition"},"As we see, there are two suspicious open ports: 5000 and 8080. So it is obvious that the frontend and backend are still directly accessible in the host network. This should be fixed!"),(0,o.kt)("p",{parentName:"admonition"},"You are done when the port scan report looks something like this:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-05 12:39 UTC\nNmap scan report for localhost (127.0.0.1)\nHost is up (0.0000040s latency).\nOther addresses for localhost (not scanned): ::1\nNot shown: 998 closed tcp ports (reset)\nPORT STATE SERVICE\n80/tcp filtered http\n111/tcp open rpcbind\n\nNmap done: 1 IP address (1 host up) scanned in 1.28 seconds\n"))))}c.isMDXComponent=!0},6715:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/adminer-fea0b2f85933608d9bba6981eeb033c7.png"},9594:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/redmine2024-c58915fec1682f9c84e2ba48332a3f85.png"},7389:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/back-front-redis-and-database-5aaf7f70f4e7f9f0873e2be9710ea5e6.png"},9462:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/back-front-redis-database-and-nginx-6cf5c082483c2a445501cafe19017fbc.png"}}]); \ No newline at end of file diff --git a/assets/js/0da1f8d4.4af74ffd.js b/assets/js/0da1f8d4.4af74ffd.js new file mode 100644 index 00000000..f3b66226 --- /dev/null +++ b/assets/js/0da1f8d4.4af74ffd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[139],{3905:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>u});var o=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=o.createContext({}),p=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},d=function(e){var n=p(e.components);return o.createElement(l.Provider,{value:n},e.children)},c="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},h=o.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),c=p(t),h=a,u=c["".concat(l,".").concat(h)]||c[h]||m[h]||r;return t?o.createElement(u,i(i({ref:n},d),{},{components:t})):o.createElement(u,i({ref:n},d))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,i=new Array(r);i[0]=h;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[c]="string"==typeof e?e:a,i[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>m,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var o=t(7462),a=(t(7294),t(3905));const r={title:"Containers in development"},i=void 0,s={unversionedId:"part-2/section-4",id:"part-2/section-4",title:"Containers in development",description:"Containers are not only great in production. They can be used in development environments as well and offer several benefits. The same works-on-my-machine problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!",source:"@site/docs/part-2/section-4.md",sourceDirName:"part-2",slug:"/part-2/section-4",permalink:"/part-2/section-4",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/part-2/section-4.md",tags:[],version:"current",frontMatter:{title:"Containers in development"},sidebar:"materialSidebar",previous:{title:"Volumes in action",permalink:"/part-2/section-3"},next:{title:"Summary",permalink:"/part-2/section-5"}},l={},p=[{value:"Exercise 2.11",id:"exercise-211",level:2}],d={toc:p},c="wrapper";function m(e){let{components:n,...t}=e;return(0,a.kt)(c,(0,o.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Containers are not only great in production. They can be used in development environments as well and offer several benefits. The same ",(0,a.kt)("em",{parentName:"p"},"works-on-my-machine")," problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!"),(0,a.kt)("p",null,"For example, a ",(0,a.kt)("a",{parentName:"p",href:"https://toska.dev/"},"software development team")," at the University of Helsinki has a fully ",(0,a.kt)("a",{parentName:"p",href:"https://ethesis.helsinki.fi/repository/handle/123456789/30995"},"containerized development environment"),". The principle in all development projects is to have a setup so that a new developer only needs to install Docker and clone the project code from GitHub to get started. Not a single dependency is ever installed on to host machine, Git, Docker and the text editor of choice are the only things that are needed."),(0,a.kt)("p",null,'Even if your application is not completely containerized during development, containers can be very helpful. For example, say you need MongoDB version 4.0.22 installed in port 5656. It\'s now an oneliner: "docker run -p 5656:27017 mongo:4.0.22" (MongoDB uses 27017 as the default port).'),(0,a.kt)("p",null,"Let's containerize a NodeJS development environment. As you perhaps know ",(0,a.kt)("a",{parentName:"p",href:"https://nodejs.org/en/"},"NodeJS")," is a cross-platform JavaScript runtime that makes it possible to run JavaScript in your machine, servers and embedded devices, among many other platforms"),(0,a.kt)("p",null,"The setup requires some expertise in the way how NodeJS works. Here is a simplified explanation if you're not familiar: libraries are defined in ",(0,a.kt)("inlineCode",{parentName:"p"},"package.json")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"package-lock.json")," and installed with ",(0,a.kt)("inlineCode",{parentName:"p"},"npm install"),". ",(0,a.kt)("a",{parentName:"p",href:"https://www.npmjs.com/"},"npm")," is the Node package manager."),(0,a.kt)("p",null,"To run the application with the packages we have a script defined in package.json that instructs Node to execute index.js, the main/entry file in this case the script is executed with ",(0,a.kt)("inlineCode",{parentName:"p"},"npm start"),". The application already includes code to watch for changes in the filesystem and restart the application if any changes are detected."),(0,a.kt)("p",null,'The project "node-dev-env" is here ',(0,a.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/node-dev-env"},"https://github.com/docker-hy/material-applications/tree/main/node-dev-env"),". We have already included a development Dockerfile and a helpful docker-compose.yml."),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Dockerfile")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-Dockerfile"},"FROM node:16\n\nWORKDIR /usr/src/app\n\nCOPY package* ./\n\nRUN npm install\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"docker-compose.yml")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},"version: '3.8'\n\nservices:\n node-dev-env:\n build: . # Build with the Dockerfile here\n command: npm start # Run npm start as the command\n ports:\n - 3000:3000 # The app uses port 3000 by default, publish it as 3000\n volumes:\n - ./:/usr/src/app # Let us modify the contents of the container locally\n - node_modules:/usr/src/app/node_modules # A bit of node magic, this ensures the dependencies built for the image are not available locally.\n container_name: node-dev-env # Container name for convenience\n\nvolumes: # This is required for the node_modules named volume\n node_modules:\n")),(0,a.kt)("p",null,"And that's it. We'll use volume to copy all source code inside the volume so CMD will run the application we're developing. Let's try it!"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-console"},"$\xa0docker compose up\n\n...\n\nAttaching to node-dev-env\nnode-dev-env |\nnode-dev-env | > dev-env@1.0.0 start\nnode-dev-env | > nodemon index.js\nnode-dev-env |\nnode-dev-env | [nodemon] 2.0.7\nnode-dev-env | [nodemon] to restart at any time, enter `rs`\nnode-dev-env | [nodemon] watching path(s): *.*\nnode-dev-env | [nodemon] watching extensions: js,mjs,json\nnode-dev-env | [nodemon] starting `node index.js`\nnode-dev-env | App listening in port 3000\n")),(0,a.kt)("p",null,"Great! The initial start-up is a bit slow. It is a lot faster now that the image is already built. We can rebuild the whole environment whenever we want with ",(0,a.kt)("inlineCode",{parentName:"p"},"docker compose up --build"),"."),(0,a.kt)("p",null,"Let's see if the application works. Use the browser to access ",(0,a.kt)("a",{parentName:"p",href:"http://localhost:3000"},"http://localhost:3000"),", it should do a simple plus calculation with the query params."),(0,a.kt)("p",null,"However, the calculation doesn't make sense! Let's fix the bug. I bet it's this line right here ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/blob/main/node-dev-env/index.js#L5"},"https://github.com/docker-hy/material-applications/blob/main/node-dev-env/index.js#L5")),(0,a.kt)("p",null,"When I change the line, on my host machine the application instantly notices that files have changed:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-console"},"$ docker compose up\n\n...\n\nAttaching to node-dev-env\nnode-dev-env |\nnode-dev-env | > dev-env@1.0.0 start\nnode-dev-env | > nodemon index.js\nnode-dev-env |\nnode-dev-env | [nodemon] 2.0.7\nnode-dev-env | [nodemon] to restart at any time, enter `rs`\nnode-dev-env | [nodemon] watching path(s): *.*\nnode-dev-env | [nodemon] watching extensions: js,mjs,json\nnode-dev-env | [nodemon] starting `node index.js`\nnode-dev-env | App listening in port 3000\nnode-dev-env | [nodemon] restarting due to changes...\nnode-dev-env | [nodemon] starting `node index.js`\nnode-dev-env | App listening in port 3000\n")),(0,a.kt)("p",null,"And now a page refresh shows that our code change fixed the issue. The development environment works."),(0,a.kt)("p",null,"The next exercise can be extremely easy or extremely hard. Feel free to have fun with it."),(0,a.kt)("h2",{id:"exercise-211"},"Exercise 2.11"),(0,a.kt)("admonition",{title:"Exercise 2.11",type:"info"},(0,a.kt)("p",{parentName:"admonition"}," Select some of your own development projects and start utilizing containers in the development environment."),(0,a.kt)("p",{parentName:"admonition"}," Explain what you have done. It can be anything, e.g., support for docker-compose.yml to have services (such as databases) containerized or even a fully blown containerized development environment.")),(0,a.kt)("p",null,"If you are interested in how to build a containerized development environment for a React/Node Single page web app, please have a look at the course ",(0,a.kt)("a",{parentName:"p",href:"https://fullstackopen.com"},"Full stack open")," which has one ",(0,a.kt)("a",{parentName:"p",href:"https://fullstackopen.com/en/part12/basics_of_orchestration#development-in-containers"},"chapter")," devoted to the topic."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0da1f8d4.cc15cc97.js b/assets/js/0da1f8d4.cc15cc97.js deleted file mode 100644 index 16a1f4ef..00000000 --- a/assets/js/0da1f8d4.cc15cc97.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[139],{3905:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>h});var o=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=o.createContext({}),p=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},d=function(e){var n=p(e.components);return o.createElement(l.Provider,{value:n},e.children)},c="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},u=o.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),c=p(t),u=a,h=c["".concat(l,".").concat(u)]||c[u]||m[u]||r;return t?o.createElement(h,i(i({ref:n},d),{},{components:t})):o.createElement(h,i({ref:n},d))}));function h(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,i=new Array(r);i[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[c]="string"==typeof e?e:a,i[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>m,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var o=t(7462),a=(t(7294),t(3905));const r={title:"Containers in development"},i=void 0,s={unversionedId:"part-2/section-4",id:"part-2/section-4",title:"Containers in development",description:"Containers are not only great in production. They can be used in development environments as well and offer a number of benefits. The same works-on-my-machine problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!",source:"@site/docs/part-2/section-4.md",sourceDirName:"part-2",slug:"/part-2/section-4",permalink:"/part-2/section-4",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/part-2/section-4.md",tags:[],version:"current",frontMatter:{title:"Containers in development"},sidebar:"materialSidebar",previous:{title:"Volumes in action",permalink:"/part-2/section-3"},next:{title:"Summary",permalink:"/part-2/section-5"}},l={},p=[{value:"Exercise 2.11",id:"exercise-211",level:2}],d={toc:p},c="wrapper";function m(e){let{components:n,...t}=e;return(0,a.kt)(c,(0,o.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Containers are not only great in production. They can be used in development environments as well and offer a number of benefits. The same ",(0,a.kt)("em",{parentName:"p"},"works-on-my-machine")," problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!"),(0,a.kt)("p",null,"For an example, a ",(0,a.kt)("a",{parentName:"p",href:"https://toska.dev/"},"software development team")," at the University of Helsinki has a fully ",(0,a.kt)("a",{parentName:"p",href:"https://ethesis.helsinki.fi/repository/handle/123456789/30995"},"containerized development environment"),". The principle in all development projects is to have a setup so that a new developer only needs to install Docker and clone the project code from GitHub to get started. Not a single dependency is ever installed on to host machine, Git, Docker and the text editor of choice is only thing that is needed."),(0,a.kt)("p",null,'Even if your application is not completely containerized during development, containers can very helpful. For example, say you need MongoDB version 4.0.22 installed in port 5656. It\'s now a oneliner: "docker run -p 5656:27017 mongo:4.0.22" (MongoDB uses 27017 as default port).'),(0,a.kt)("p",null,"Let's containerize a NodeJS development environment. As you perhaps know ",(0,a.kt)("a",{parentName:"p",href:"https://nodejs.org/en/"},"NodeJS")," is a cross-platform JavaScript runtime that makes it possible to run JavaScript in your machine, servers and embedded devices, among many other platforms"),(0,a.kt)("p",null,"The setup requires some expertise on the way how NodeJS works. Here is a simplified explanation if you're not familiar: libraries are defined in ",(0,a.kt)("inlineCode",{parentName:"p"},"package.json")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"package-lock.json")," and installed with ",(0,a.kt)("inlineCode",{parentName:"p"},"npm install"),". ",(0,a.kt)("a",{parentName:"p",href:"https://www.npmjs.com/"},"npm")," is the Node package manager."),(0,a.kt)("p",null,"To run application with the packages we have script defined in package.json that instructs Node to execute index.js, the main/entry file in this case the script is executed with ",(0,a.kt)("inlineCode",{parentName:"p"},"npm start"),". The application already includes code to watch for changes in the filesystem and restart the application if any changes are detected."),(0,a.kt)("p",null,'The project "node-dev-env" is here ',(0,a.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/tree/main/node-dev-env"},"https://github.com/docker-hy/material-applications/tree/main/node-dev-env"),". I already included a development Dockerfile and a helpful docker-compose.yml."),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Dockerfile")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-Dockerfile"},"FROM node:16\n\nWORKDIR /usr/src/app\n\nCOPY package* ./\n\nRUN npm install\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"docker-compose.yml")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},"version: '3.8'\n\nservices:\n node-dev-env:\n build: . # Build with the Dockerfile here\n command: npm start # Run npm start as the command\n ports:\n - 3000:3000 # The app uses port 3000 by default, publish it as 3000\n volumes:\n - ./:/usr/src/app # Let us modify the contents of the container locally\n - node_modules:/usr/src/app/node_modules # A bit of node magic, this ensures the dependencies built for the image are not available locally.\n container_name: node-dev-env # Container name for convenience\n\nvolumes: # This is required for the node_modules named volume\n node_modules:\n")),(0,a.kt)("p",null,"And that's it. We'll use volume to copy all source code inside the volume so CMD will run the application we're developing. Let's try it!"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-console"},'$\xa0docker compose up\nCreating network "node-dev-env_default" with the default driver\nCreating volume "node-dev-env_node_modules" with default driver\nBuilding node-dev-env\nStep 1/4 : FROM node:14\n...\n\nAttaching to node-dev-env\nnode-dev-env |\nnode-dev-env | > dev-env@1.0.0 start /usr/src/app\nnode-dev-env | > nodemon index.js\n...\n\nnode-dev-env | App listening in port 3000\n')),(0,a.kt)("p",null,"Great! The initial start up is a bit slow. It is a lot faster now that the image is already built. We can rebuild the whole environment whenever we want with ",(0,a.kt)("inlineCode",{parentName:"p"},"docker compose up --build"),"."),(0,a.kt)("p",null,"Let's see if the application works. Use browser to access ",(0,a.kt)("a",{parentName:"p",href:"http://localhost:3000"},"http://localhost:3000"),", it should do a simple plus calculation with the query params."),(0,a.kt)("p",null,"However, the calulation doesn't make sense! Let's fix the bug. I bet it's this line right here ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/docker-hy/material-applications/blob/main/node-dev-env/index.js#L5"},"https://github.com/docker-hy/material-applications/blob/main/node-dev-env/index.js#L5")),(0,a.kt)("p",null,"When I change the line, on my host machine the application instantly notices that files have changed:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-console"},"\u25b6 docker compose up\nStarting node-dev-env ... done\nAttaching to node-dev-env\nnode-dev-env |\nnode-dev-env | > dev-env@1.0.0 start /usr/src/app\nnode-dev-env | > nodemon index.js\nnode-dev-env |\nnode-dev-env | [nodemon] 2.0.7\nnode-dev-env | [nodemon] to restart at any time, enter `rs`\nnode-dev-env | [nodemon] watching path(s): *.*\nnode-dev-env | [nodemon] watching extensions: js,mjs,json\nnode-dev-env | [nodemon] starting `node index.js`\nnode-dev-env | App listening in port 3000\nnode-dev-env | [nodemon] restarting due to changes...\nnode-dev-env | [nodemon] starting `node index.js`\nnode-dev-env | App listening in port 3000\n")),(0,a.kt)("p",null,"And now a page refresh shows that our code change fixed the issue. The development environment works."),(0,a.kt)("p",null,"The next exercise can be extremely easy or extremely hard. Feel free to have fun with it."),(0,a.kt)("h2",{id:"exercise-211"},"Exercise 2.11"),(0,a.kt)("admonition",{title:"Exercise 2.11",type:"info"},(0,a.kt)("p",{parentName:"admonition"}," Select some of your own development projects and start utilizing containers in the development environment."),(0,a.kt)("p",{parentName:"admonition"}," Explain what you have done. It can be anything, e.g., a support for docker-compose.yml to have services (such as databases) containerized or even a fully blown containerized development environment.")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.1490e561.js b/assets/js/935f2afb.483bbf22.js similarity index 75% rename from assets/js/935f2afb.1490e561.js rename to assets/js/935f2afb.483bbf22.js index bce8bd3b..fa03c341 100644 --- a/assets/js/935f2afb.1490e561.js +++ b/assets/js/935f2afb.483bbf22.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"materialSidebar":[{"type":"link","label":"DevOps with Docker","href":"/","className":"hidden","docId":"intro"},{"type":"link","label":"Getting Started","href":"/getting-started","docId":"getting-started"},{"type":"link","label":"Frequently Asked Questions","href":"/faq","docId":"faq"},{"type":"category","label":"Part 1","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 1","href":"/part-1/","docId":"part-1/index"},{"type":"link","label":"Definitions and basic concepts","href":"/part-1/section-1","docId":"part-1/section-1"},{"type":"link","label":"Running and stopping containers","href":"/part-1/section-2","docId":"part-1/section-2"},{"type":"link","label":"In-depth dive into images","href":"/part-1/section-3","docId":"part-1/section-3"},{"type":"link","label":"Defining start conditions for the container","href":"/part-1/section-4","docId":"part-1/section-4"},{"type":"link","label":"Interacting with the container via volumes and ports","href":"/part-1/section-5","docId":"part-1/section-5"},{"type":"link","label":"Utilizing tools from the Registry","href":"/part-1/section-6","docId":"part-1/section-6"},{"type":"link","label":"Summary","href":"/part-1/section-7","docId":"part-1/section-7"}],"href":"/category/part-1"},{"type":"category","label":"Part 2","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 2","href":"/part-2/","docId":"part-2/index"},{"type":"link","label":"Migrating to Docker Compose","href":"/part-2/section-1","docId":"part-2/section-1"},{"type":"link","label":"Docker networking","href":"/part-2/section-2","docId":"part-2/section-2"},{"type":"link","label":"Volumes in action","href":"/part-2/section-3","docId":"part-2/section-3"},{"type":"link","label":"Containers in development","href":"/part-2/section-4","docId":"part-2/section-4"},{"type":"link","label":"Summary","href":"/part-2/section-5","docId":"part-2/section-5"}],"href":"/category/part-2"},{"type":"category","label":"Part 3","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 3","href":"/part-3/","docId":"part-3/index"},{"type":"link","label":"Official Images and trust","href":"/part-3/section-1","docId":"part-3/section-1"},{"type":"link","label":"Deployment pipelines","href":"/part-3/section-2","docId":"part-3/section-2"},{"type":"link","label":"Using a non-root user","href":"/part-3/section-3","docId":"part-3/section-3"},{"type":"link","label":"Optimizing the image size","href":"/part-3/section-4","docId":"part-3/section-4"},{"type":"link","label":"Multi-host environments","href":"/part-3/section-5","docId":"part-3/section-5"},{"type":"link","label":"End","href":"/part-3/section-6","docId":"part-3/section-6"}],"href":"/category/part-3"},{"type":"link","label":"Credits","href":"/credits","className":"hidden","docId":"credits"}]},"docs":{"credits":{"id":"credits","title":"Credits","description":"The DevOps with Docker course was created by Jami Kousa with the help of University of Helsinki\'s Tietojenk\xe4sittelytieteen osaston sovelluskehitysakatemia (Toska) and numerous course attendees. This material is based on gist by Matti Paksula. You can help develop the course material as well.","sidebar":"materialSidebar"},"faq":{"id":"faq","title":"Frequently Asked Questions","description":"Prerequisites","sidebar":"materialSidebar"},"getting-started":{"id":"getting-started","title":"Getting Started","description":"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it\'s important to read the material carefully and complete the exercises to develop the necessary skills.","sidebar":"materialSidebar"},"intro":{"id":"intro","title":"DevOps with Docker","description":"This course provides an introduction to container technologies, with a particular focus on Docker and container orchestration using Docker Compose. Containers are a lightweight, portable way to package and deploy software applications. Throughout the course, we\'ll explore the various components of web services, such as reverse proxies and databases, and how they can be deployed using Docker.","sidebar":"materialSidebar"},"part-1/index":{"id":"part-1/index","title":"Introduction to Part 1","description":"This part introduces containerization with Docker and relevant concepts such as image and volume. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-1/section-1":{"id":"part-1/section-1","title":"Definitions and basic concepts","description":"What is DevOps?","sidebar":"materialSidebar"},"part-1/section-2":{"id":"part-1/section-2","title":"Running and stopping containers","description":"Next we will start using a more useful image than hello-world. We can run Ubuntu just with docker run ubuntu.","sidebar":"materialSidebar"},"part-1/section-3":{"id":"part-1/section-3","title":"In-depth dive into images","description":"Images are the basic building blocks for containers and other images. When you \\"containerize\\" an application you work towards creating the image.","sidebar":"materialSidebar"},"part-1/section-4":{"id":"part-1/section-4","title":"Defining start conditions for the container","description":"Next, we will start moving towards a more meaningful image. yt-dlp is a program that downloads YouTube and Imgur videos. Let\'s add it to an image - but this time, we will change our process. Instead of our current process where we add things to the Dockerfile and hope it works, let\'s try another approach. This time we will open up an interactive session and test stuff before \\"storing\\" it in our Dockerfile.","sidebar":"materialSidebar"},"part-1/section-5":{"id":"part-1/section-5","title":"Interacting with the container via volumes and ports","description":"Let us get back to yt-dlp. It works yes, but it is quite laborious to get the downloaded videos to the host machine.","sidebar":"materialSidebar"},"part-1/section-6":{"id":"part-1/section-6","title":"Utilizing tools from the Registry","description":"As we\'ve already seen it should be possible to containerize almost any project. Since we are in between Dev and Ops let\'s pretend that some developer teammates of ours did an application with a README that instructs what to install and how to run the application. Now we as the container experts can containerize it in seconds.","sidebar":"materialSidebar"},"part-1/section-7":{"id":"part-1/section-7","title":"Summary","description":"We started by learning what Docker container and image mean. Basically we started from an empty ubuntu with nothing installed into it. It\'s also possible to start from something else, but for now ubuntu had been enough.","sidebar":"materialSidebar"},"part-2/index":{"id":"part-2/index","title":"Introduction to Part 2","description":"This part introduces container orchestration with Docker Compose and relevant concepts such as docker network. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-2/section-1":{"id":"part-2/section-1","title":"Migrating to Docker Compose","description":"Even with a simple image, we\'ve already been dealing with plenty of command line options in both building, pushing and running the image.","sidebar":"materialSidebar"},"part-2/section-2":{"id":"part-2/section-2","title":"Docker networking","description":"Connecting two services such as a server and its database in docker can be achieved with a Docker network. In addition to starting services listed in docker-compose.yml Docker Compose automatically creates and joins both containers into a network with a DNS. Each service is named after the name given in the docker-compose.yml file. As such, containers can reference each other simply with their service names, which is different from the container name.","sidebar":"materialSidebar"},"part-2/section-3":{"id":"part-2/section-3","title":"Volumes in action","description":"Next we\'re going to set up the project management application Redmine, a PostgreSQL database and Adminer, a graphical interface for database administration.","sidebar":"materialSidebar"},"part-2/section-4":{"id":"part-2/section-4","title":"Containers in development","description":"Containers are not only great in production. They can be used in development environments as well and offer a number of benefits. The same works-on-my-machine problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!","sidebar":"materialSidebar"},"part-2/section-5":{"id":"part-2/section-5","title":"Summary","description":"Again we started from the ground up by learning how to translate non-compose setup into docker-compose.yml and ran with it. Compose gave us also a few handy completely new features that we didn\'t even know we needed, networks.","sidebar":"materialSidebar"},"part-3/index":{"id":"part-3/index","title":"Introduction to Part 3","description":"This part introduces production-ready practices such as container optimization and deployment pipelines. We\'ll also familiarize ourselves with other container orchestration solutions. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-3/section-1":{"id":"part-3/section-1","title":"Official Images and trust","description":"We\'ve focused on using Docker as a tool to solve various types of problems. Meanwhile we have decided to push some of the issues until later and completely ignored others.","sidebar":"materialSidebar"},"part-3/section-2":{"id":"part-3/section-2","title":"Deployment pipelines","description":"CI/CD pipeline (sometimes called deployment pipeline) is a corner stone of DevOps.","sidebar":"materialSidebar"},"part-3/section-3":{"id":"part-3/section-3","title":"Using a non-root user","description":"Let\'s get back to the youtube-dl application, that we for last time worked with it Part 2.","sidebar":"materialSidebar"},"part-3/section-4":{"id":"part-3/section-4","title":"Optimizing the image size","description":"A small image size has many advantages, firstly, it takes much less time to pull a small image from the registry. Another thing is the security: the bigger your image is the larger the surface area for an attack it has.","sidebar":"materialSidebar"},"part-3/section-5":{"id":"part-3/section-5","title":"Multi-host environments","description":"Now that we\'ve mastered containers in small systems with Docker Compose it\'s time to look beyond what the tools we practiced are capable of. In situations where we have more than a single host machine we cannot rely solely on Docker. However, Docker does contain other tools to help us with automatic deployment, scaling and management of dockerized applications.","sidebar":"materialSidebar"},"part-3/section-6":{"id":"part-3/section-6","title":"End","description":"Remember to mark your exercises in the submission application! Instructions on how and what to submit are on the getting started page.","sidebar":"materialSidebar"}}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"materialSidebar":[{"type":"link","label":"DevOps with Docker","href":"/","className":"hidden","docId":"intro"},{"type":"link","label":"Getting Started","href":"/getting-started","docId":"getting-started"},{"type":"link","label":"Frequently Asked Questions","href":"/faq","docId":"faq"},{"type":"category","label":"Part 1","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 1","href":"/part-1/","docId":"part-1/index"},{"type":"link","label":"Definitions and basic concepts","href":"/part-1/section-1","docId":"part-1/section-1"},{"type":"link","label":"Running and stopping containers","href":"/part-1/section-2","docId":"part-1/section-2"},{"type":"link","label":"In-depth dive into images","href":"/part-1/section-3","docId":"part-1/section-3"},{"type":"link","label":"Defining start conditions for the container","href":"/part-1/section-4","docId":"part-1/section-4"},{"type":"link","label":"Interacting with the container via volumes and ports","href":"/part-1/section-5","docId":"part-1/section-5"},{"type":"link","label":"Utilizing tools from the Registry","href":"/part-1/section-6","docId":"part-1/section-6"},{"type":"link","label":"Summary","href":"/part-1/section-7","docId":"part-1/section-7"}],"href":"/category/part-1"},{"type":"category","label":"Part 2","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 2","href":"/part-2/","docId":"part-2/index"},{"type":"link","label":"Migrating to Docker Compose","href":"/part-2/section-1","docId":"part-2/section-1"},{"type":"link","label":"Docker networking","href":"/part-2/section-2","docId":"part-2/section-2"},{"type":"link","label":"Volumes in action","href":"/part-2/section-3","docId":"part-2/section-3"},{"type":"link","label":"Containers in development","href":"/part-2/section-4","docId":"part-2/section-4"},{"type":"link","label":"Summary","href":"/part-2/section-5","docId":"part-2/section-5"}],"href":"/category/part-2"},{"type":"category","label":"Part 3","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction to Part 3","href":"/part-3/","docId":"part-3/index"},{"type":"link","label":"Official Images and trust","href":"/part-3/section-1","docId":"part-3/section-1"},{"type":"link","label":"Deployment pipelines","href":"/part-3/section-2","docId":"part-3/section-2"},{"type":"link","label":"Using a non-root user","href":"/part-3/section-3","docId":"part-3/section-3"},{"type":"link","label":"Optimizing the image size","href":"/part-3/section-4","docId":"part-3/section-4"},{"type":"link","label":"Multi-host environments","href":"/part-3/section-5","docId":"part-3/section-5"},{"type":"link","label":"End","href":"/part-3/section-6","docId":"part-3/section-6"}],"href":"/category/part-3"},{"type":"link","label":"Credits","href":"/credits","className":"hidden","docId":"credits"}]},"docs":{"credits":{"id":"credits","title":"Credits","description":"The DevOps with Docker course was created by Jami Kousa with the help of University of Helsinki\'s Tietojenk\xe4sittelytieteen osaston sovelluskehitysakatemia (Toska) and numerous course attendees. This material is based on gist by Matti Paksula. You can help develop the course material as well.","sidebar":"materialSidebar"},"faq":{"id":"faq","title":"Frequently Asked Questions","description":"Prerequisites","sidebar":"materialSidebar"},"getting-started":{"id":"getting-started","title":"Getting Started","description":"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it\'s important to read the material carefully and complete the exercises to develop the necessary skills.","sidebar":"materialSidebar"},"intro":{"id":"intro","title":"DevOps with Docker","description":"This course provides an introduction to container technologies, with a particular focus on Docker and container orchestration using Docker Compose. Containers are a lightweight, portable way to package and deploy software applications. Throughout the course, we\'ll explore the various components of web services, such as reverse proxies and databases, and how they can be deployed using Docker.","sidebar":"materialSidebar"},"part-1/index":{"id":"part-1/index","title":"Introduction to Part 1","description":"This part introduces containerization with Docker and relevant concepts such as image and volume. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-1/section-1":{"id":"part-1/section-1","title":"Definitions and basic concepts","description":"What is DevOps?","sidebar":"materialSidebar"},"part-1/section-2":{"id":"part-1/section-2","title":"Running and stopping containers","description":"Next we will start using a more useful image than hello-world. We can run Ubuntu just with docker run ubuntu.","sidebar":"materialSidebar"},"part-1/section-3":{"id":"part-1/section-3","title":"In-depth dive into images","description":"Images are the basic building blocks for containers and other images. When you \\"containerize\\" an application you work towards creating the image.","sidebar":"materialSidebar"},"part-1/section-4":{"id":"part-1/section-4","title":"Defining start conditions for the container","description":"Next, we will start moving towards a more meaningful image. yt-dlp is a program that downloads YouTube and Imgur videos. Let\'s add it to an image - but this time, we will change our process. Instead of our current process where we add things to the Dockerfile and hope it works, let\'s try another approach. This time we will open up an interactive session and test stuff before \\"storing\\" it in our Dockerfile.","sidebar":"materialSidebar"},"part-1/section-5":{"id":"part-1/section-5","title":"Interacting with the container via volumes and ports","description":"Let us get back to yt-dlp. It works yes, but it is quite laborious to get the downloaded videos to the host machine.","sidebar":"materialSidebar"},"part-1/section-6":{"id":"part-1/section-6","title":"Utilizing tools from the Registry","description":"As we\'ve already seen it should be possible to containerize almost any project. Since we are in between Dev and Ops let\'s pretend that some developer teammates of ours did an application with a README that instructs what to install and how to run the application. Now we as the container experts can containerize it in seconds.","sidebar":"materialSidebar"},"part-1/section-7":{"id":"part-1/section-7","title":"Summary","description":"We started by learning what Docker container and image mean. Basically we started from an empty ubuntu with nothing installed into it. It\'s also possible to start from something else, but for now ubuntu had been enough.","sidebar":"materialSidebar"},"part-2/index":{"id":"part-2/index","title":"Introduction to Part 2","description":"This part introduces container orchestration with Docker Compose and relevant concepts such as docker network. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-2/section-1":{"id":"part-2/section-1","title":"Migrating to Docker Compose","description":"Even with a simple image, we\'ve already been dealing with plenty of command line options in both building, pushing and running the image.","sidebar":"materialSidebar"},"part-2/section-2":{"id":"part-2/section-2","title":"Docker networking","description":"Connecting two services such as a server and its database in docker can be achieved with a Docker network. In addition to starting services listed in docker-compose.yml Docker Compose automatically creates and joins both containers into a network with a DNS. Each service is named after the name given in the docker-compose.yml file. As such, containers can reference each other simply with their service names, which is different from the container name.","sidebar":"materialSidebar"},"part-2/section-3":{"id":"part-2/section-3","title":"Volumes in action","description":"Next we\'re going to set up the project management application Redmine, a PostgreSQL database and Adminer, a graphical interface for database administration.","sidebar":"materialSidebar"},"part-2/section-4":{"id":"part-2/section-4","title":"Containers in development","description":"Containers are not only great in production. They can be used in development environments as well and offer several benefits. The same works-on-my-machine problem is faced often when a new developer joins the team. Not to mention the headache of switching runtime versions or a local database!","sidebar":"materialSidebar"},"part-2/section-5":{"id":"part-2/section-5","title":"Summary","description":"Again we started from the ground up by learning how to translate non-compose setup into docker-compose.yml and ran with it. Compose gave us also a few handy completely new features that we didn\'t even know we needed, networks.","sidebar":"materialSidebar"},"part-3/index":{"id":"part-3/index","title":"Introduction to Part 3","description":"This part introduces production-ready practices such as container optimization and deployment pipelines. We\'ll also familiarize ourselves with other container orchestration solutions. By the end of this part you are able to:","sidebar":"materialSidebar"},"part-3/section-1":{"id":"part-3/section-1","title":"Official Images and trust","description":"We\'ve focused on using Docker as a tool to solve various types of problems. Meanwhile we have decided to push some of the issues until later and completely ignored others.","sidebar":"materialSidebar"},"part-3/section-2":{"id":"part-3/section-2","title":"Deployment pipelines","description":"CI/CD pipeline (sometimes called deployment pipeline) is a corner stone of DevOps.","sidebar":"materialSidebar"},"part-3/section-3":{"id":"part-3/section-3","title":"Using a non-root user","description":"Let\'s get back to the youtube-dl application, that we for last time worked with it Part 2.","sidebar":"materialSidebar"},"part-3/section-4":{"id":"part-3/section-4","title":"Optimizing the image size","description":"A small image size has many advantages, firstly, it takes much less time to pull a small image from the registry. Another thing is the security: the bigger your image is the larger the surface area for an attack it has.","sidebar":"materialSidebar"},"part-3/section-5":{"id":"part-3/section-5","title":"Multi-host environments","description":"Now that we\'ve mastered containers in small systems with Docker Compose it\'s time to look beyond what the tools we practiced are capable of. In situations where we have more than a single host machine we cannot rely solely on Docker. However, Docker does contain other tools to help us with automatic deployment, scaling and management of dockerized applications.","sidebar":"materialSidebar"},"part-3/section-6":{"id":"part-3/section-6","title":"End","description":"Remember to mark your exercises in the submission application! Instructions on how and what to submit are on the getting started page.","sidebar":"materialSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/d589d3a7.bc703d3f.js b/assets/js/d589d3a7.bc703d3f.js deleted file mode 100644 index 6e6c1a4d..00000000 --- a/assets/js/d589d3a7.bc703d3f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[162],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>m});var r=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function i(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function a(e){for(var t=1;t=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var l=r.createContext({}),c=function(e){var t=r.useContext(l),o=t;return e&&(o="function"==typeof e?e(t):a(a({},t),e)),o},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var o=e.components,n=e.mdxType,i=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=c(o),h=n,m=d["".concat(l,".").concat(h)]||d[h]||p[h]||i;return o?r.createElement(m,a(a({ref:t},u),{},{components:o})):r.createElement(m,a({ref:t},u))}));function m(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=o.length,a=new Array(i);a[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:n,a[1]=s;for(var c=2;c{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>c});var r=o(7462),n=(o(7294),o(3905));const i={sidebar_position:2},a="Getting Started",s={unversionedId:"getting-started",id:"getting-started",title:"Getting Started",description:"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it's important to read the material carefully and complete the exercises to develop the necessary skills.",source:"@site/docs/getting-started.md",sourceDirName:".",slug:"/getting-started",permalink:"/getting-started",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/getting-started.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"materialSidebar",previous:{title:"DevOps with Docker",permalink:"/"},next:{title:"Frequently Asked Questions",permalink:"/faq"}},l={},c=[{value:"Prerequisites",id:"prerequisites",level:3},{value:"Updating of the material for the 2024 edition",id:"updating-of-the-material-for-the-2024-edition",level:3},{value:"About different architectures and contributing",id:"about-different-architectures-and-contributing",level:3},{value:"Grading",id:"grading",level:3},{value:"Learning objectives",id:"learning-objectives",level:3},{value:"Where to find information about the course?",id:"where-to-find-information-about-the-course",level:3},{value:"Discord",id:"discord",level:3},{value:"Installing Docker",id:"installing-docker",level:2},{value:"Deadline",id:"deadline",level:2},{value:"General guidance",id:"general-guidance",level:2},{value:"How to submit the exercises",id:"how-to-submit-the-exercises",level:2},{value:"Completing",id:"completing",level:2}],u={toc:c},d="wrapper";function p(e){let{components:t,...i}=e;return(0,n.kt)(d,(0,r.Z)({},u,i,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"getting-started"},"Getting Started"),(0,n.kt)("p",null,"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it's important to read the material carefully and complete the exercises to develop the necessary skills."),(0,n.kt)("p",null,"To pass the course, you will need to complete all of the exercises. However, one exercise can be skipped per part, except for the exercises marked as mandatory. The mandatory exercises cannot be skipped."),(0,n.kt)("p",null,"The exercises are designed to reinforce the material covered in each part and are placed at strategic points in the course to ensure that you have learned the necessary skills before attempting each exercise. You can complete the exercises at your own pace, and there is no deadline for submission outside of the last date when the entire course ends."),(0,n.kt)("p",null,"When submitting your exercises, please follow the instructions provided in the course material. Exercises should be submitted in a specific format, which will be outlined in the instructions for each exercise."),(0,n.kt)("p",null,"We hope that you enjoy the course and find it informative and engaging. Good luck!"),(0,n.kt)("h3",{id:"prerequisites"},"Prerequisites"),(0,n.kt)("p",null,"The course is suitable for anyone interested in Docker or containerization and has at least some experience with the Linux command line. It also helps if you have some experience in web development."),(0,n.kt)("h3",{id:"updating-of-the-material-for-the-2024-edition"},"Updating of the material for the 2024 edition"),(0,n.kt)("p",null,"The 2024 edition of the course starts officially on 11th March. The material is currently being updated. At the time of writing (11th March) the following parts have already been updated"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Part 1"),(0,n.kt)("li",{parentName:"ul"},"Part 2 up to and including chapter ",(0,n.kt)("em",{parentName:"li"},"Docker networking"))),(0,n.kt)("p",null,"You may continue already beyond the updated material but beware, there might be some outdated content!"),(0,n.kt)("h3",{id:"about-different-architectures-and-contributing"},"About different architectures and contributing"),(0,n.kt)("p",null,"Please note that while Docker runs on all major operating systems and even on ARM architecture, this course material may not cover platform-specific details for all operating systems. However, we've had students successfully complete the course using a variety of machines and operating systems."),(0,n.kt)("p",null,"If you encounter any issues while working through the course material on your particular system, we recommend consulting the Docker documentation or seeking help on the course forums. Our community is here to support you and help you succeed in the course!"),(0,n.kt)("p",null,"We welcome contributions to the course material from students and other members of the DevOps community! If you notice any mistakes, typos, or errors in the material, please consider submitting a pull request to the course repository on GitHub."),(0,n.kt)("p",null,"Thank you in advance for your contributions to this open source project!"),(0,n.kt)("h3",{id:"grading"},"Grading"),(0,n.kt)("p",null,"Passing this course requires you to do the exercises for each part. This means generally every exercise, but you are allowed to skip one non-mandatory exercise in each part. Some of the exercises are mandatory and can not be skipped."),(0,n.kt)("p",null,"This course is worth 1-3 credits depending on the completed parts. Completing part 1 gives you 1 credit. Completing parts 1 and 2 is worth 2 credits. Completing all of the parts will grant you 3 credits."),(0,n.kt)("p",null,"There are additional instructions for completion after each part and at the end of this page."),(0,n.kt)("h3",{id:"learning-objectives"},"Learning objectives"),(0,n.kt)("p",null,"Part 1: DevOps with Docker (",(0,n.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/toteutus/otm-4bd45ab8-8b23-4973-a918-a6b6f7bbb347/TKT21036"},"TKT21036"),")"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Understand the fundamental concepts of Docker, including images and containers."),(0,n.kt)("li",{parentName:"ul"},"Learn how to build Docker images for existing projects and run them."),(0,n.kt)("li",{parentName:"ul"},"Understand how Docker can simplify the development process.")),(0,n.kt)("p",null,"Part 2: DevOps with Docker: docker-compose (",(0,n.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/toteutus/otm-c73ef1c6-8fb0-42e8-9052-ef59b01cb409/TKT21037"},"TKT21037"),")"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Learn how to manage complex multi-container applications with Docker Compose."),(0,n.kt)("li",{parentName:"ul"},"Understand the role of Docker Compose in container orchestration"),(0,n.kt)("li",{parentName:"ul"},"Practice deploying and managing real-world applications using Docker Compose.")),(0,n.kt)("p",null,"Part 3: DevOps with Docker: security and optimization (",(0,n.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/opintojakso/hy-CU-142971306-2020-08-01/TKT21038"},"TKT21038"),")"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Learn how to optimize Docker images for production, including reducing image size and improving security."),(0,n.kt)("li",{parentName:"ul"},"Understand the limitations of using Docker Compose in production environments and the need for more advanced orchestration tools."),(0,n.kt)("li",{parentName:"ul"},"Explore alternative container orchestration solutions, including Kubernetes.")),(0,n.kt)("h3",{id:"where-to-find-information-about-the-course"},"Where to find information about the course?"),(0,n.kt)("p",null,"All of the details you need to complete the course should be found on this page. If something is missing or unclear after reading this page, please contact ",(0,n.kt)("a",{parentName:"p",href:"mailto:matti.luukkainen@helsinki.fi"},"matti.luukkainen@helsinki.fi")," or get in touch through Discord."),(0,n.kt)("h3",{id:"discord"},"Discord"),(0,n.kt)("p",null,"This course has a Discord group where we discuss everything about the course. Support is available almost 24/7, with the discussion being in both English and Finnish."),(0,n.kt)("p",null,"Join our discord group ",(0,n.kt)("a",{parentName:"p",href:"https://study.cs.helsinki.fi/discord/join/docker"},"here"),"."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"All")," inappropriate, degrading or discriminating comments on the channel are prohibited and will lead to action taken against the commenter."),(0,n.kt)("h1",{id:"warning-before-installing-docker"},"Warning: Before installing Docker"),(0,n.kt)("p",null,"Containers leverage the power of your own operating system. As such ",(0,n.kt)("strong",{parentName:"p"},"by default")," any containerized application, or user who has external access to your container, would have super user privileges to your computer."),(0,n.kt)("p",null,"I will try my best to alert you of potential risks as we encounter them, but due to the structure of the course we will focus on security in part 3."),(0,n.kt)("p",null,"Please keep this in mind as you move through the installation and exercises. If you ever feel unsure about what you're doing, come to the Discord channel and have a chat with us."),(0,n.kt)("h2",{id:"installing-docker"},"Installing Docker"),(0,n.kt)("p",null,"Use the official documentation to find download instructions for docker-ce for the platform of your choice:"),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://docs.docker.com/install/linux/docker-ce/ubuntu/"},"Ubuntu")),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://docs.docker.com/docker-for-mac/install/"},"MacOS")),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://docs.docker.com/docker-for-windows/install/"},"Windows")),(0,n.kt)("p",null,"Confirm that Docker installed correctly by opening a terminal and running ",(0,n.kt)("inlineCode",{parentName:"p"},"docker -v")," to see the installed version."),(0,n.kt)("admonition",{title:"Docker group",type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"To avoid writing sudos you may consider ",(0,n.kt)("a",{parentName:"p",href:"https://docs.docker.com/install/linux/linux-postinstall/"},"adding yourself to docker group")),(0,n.kt)("p",{parentName:"admonition"},"Keep in mind that if you do so, you can now run containers without sudo and containers give you super user access to the computer.")),(0,n.kt)("h2",{id:"deadline"},"Deadline"),(0,n.kt)("p",null,"The sign up for ECTS credits and the course ends 16.6.2024! After that course is locked and submissions can no longer be made or credits earned. As the certificate is received through submissions, you have to submit everything before the course ends. More details under completion and after each part."),(0,n.kt)("h2",{id:"general-guidance"},"General guidance"),(0,n.kt)("p",null,(0,n.kt)("em",{parentName:"p"},"Do not alter the code of the projects, unless by pull-requests to the original projects")),(0,n.kt)("p",null,"You do not need to touch Ruby, Java, Javascript or Python code during this course. You may have to read their error messages."),(0,n.kt)("p",null,"Visit the Discord channel if you are stuck!"),(0,n.kt)("h2",{id:"how-to-submit-the-exercises"},"How to submit the exercises"),(0,n.kt)("p",null,"Make a repository to GitHub and publish your solutions in clearly ordered files / folders. If you need help publishing using Git you should refer to their ",(0,n.kt)("a",{parentName:"p",href:"https://guides.github.com/activities/hello-world/"},"guide"),". Make sure that the repository is available to us, either by using a public repository or a private repository and adding Jakousa and mluukkai as collaborators."),(0,n.kt)("p",null,"Most of the exercises will be focused on a Dockerfile and/or docker-compose.yml. In those cases, submitting the file is enough. In other cases, a picture or copy-paste from your command line or a link to Docker Hub and/or project inside the repository is enough. For the command line exercises at start the command ",(0,n.kt)("a",{parentName:"p",href:"https://linux.die.net/man/1/script"},"script")," may be helpful."),(0,n.kt)("p",null,"Because the course exercises are designed to build upon each other, it's more important that you document the exercises for yourself. We will be looking at the submissions of the later exercises as they are more demanding."),(0,n.kt)("p",null,"When you have completed a part, use the ",(0,n.kt)("a",{parentName:"p",href:"https://studies.cs.helsinki.fi/stats/courses/docker2024"},"submission application")," to mark your exercises. You can ",(0,n.kt)("strong",{parentName:"p"},"not")," edit a submission, so make sure you have completed enough exercises for a part before submitting."),(0,n.kt)("h2",{id:"completing"},"Completing"),(0,n.kt)("p",null,"The certificate is available from the small icon beneath your submissions!"),(0,n.kt)("p",null,'After you have returned all of the required exercises and wish to end your course completion and want the ECTS credits press the following button in the submission application (ignore the message about an "exam" as there is no exam in this course):'),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Incomplete course",src:o(6795).Z,width:"874",height:"188"})),(0,n.kt)("p",null,'After that, double-check that the application has the message "Course marked as completed" and the date. If the date is not visible, we have not been notified.'),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Completed course",src:o(38).Z,width:"482",height:"469"})))}p.isMDXComponent=!0},38:(e,t,o)=>{o.d(t,{Z:()=>r});const r=o.p+"assets/images/completed_course-1c9c27f6aefc0214cb0b511b6358980c.png"},6795:(e,t,o)=>{o.d(t,{Z:()=>r});const r=o.p+"assets/images/incomplete_course-8a93bc802c0307b99b884cb844e664ff.png"}}]); \ No newline at end of file diff --git a/assets/js/d589d3a7.e30e7661.js b/assets/js/d589d3a7.e30e7661.js new file mode 100644 index 00000000..07db8758 --- /dev/null +++ b/assets/js/d589d3a7.e30e7661.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[162],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>m});var r=o(7294);function i(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function n(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function a(e){for(var t=1;t=0||(i[o]=e[o]);return i}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(i[o]=e[o])}return i}var l=r.createContext({}),c=function(e){var t=r.useContext(l),o=t;return e&&(o="function"==typeof e?e(t):a(a({},t),e)),o},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var o=e.components,i=e.mdxType,n=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=c(o),h=i,m=d["".concat(l,".").concat(h)]||d[h]||p[h]||n;return o?r.createElement(m,a(a({ref:t},u),{},{components:o})):r.createElement(m,a({ref:t},u))}));function m(e,t){var o=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var n=o.length,a=new Array(n);a[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:i,a[1]=s;for(var c=2;c{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>n,metadata:()=>s,toc:()=>c});var r=o(7462),i=(o(7294),o(3905));const n={sidebar_position:2},a="Getting Started",s={unversionedId:"getting-started",id:"getting-started",title:"Getting Started",description:"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it's important to read the material carefully and complete the exercises to develop the necessary skills.",source:"@site/docs/getting-started.md",sourceDirName:".",slug:"/getting-started",permalink:"/getting-started",draft:!1,editUrl:"https://github.com/docker-hy/docker-hy.github.io/blob/master/docs/getting-started.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"materialSidebar",previous:{title:"DevOps with Docker",permalink:"/"},next:{title:"Frequently Asked Questions",permalink:"/faq"}},l={},c=[{value:"Prerequisites",id:"prerequisites",level:3},{value:"Updating of the material for the 2024 edition",id:"updating-of-the-material-for-the-2024-edition",level:3},{value:"About different architectures and contributing",id:"about-different-architectures-and-contributing",level:3},{value:"Grading",id:"grading",level:3},{value:"Learning objectives",id:"learning-objectives",level:3},{value:"Where to find information about the course?",id:"where-to-find-information-about-the-course",level:3},{value:"Discord",id:"discord",level:3},{value:"Installing Docker",id:"installing-docker",level:2},{value:"Deadline",id:"deadline",level:2},{value:"General guidance",id:"general-guidance",level:2},{value:"How to submit the exercises",id:"how-to-submit-the-exercises",level:2},{value:"Completing",id:"completing",level:2}],u={toc:c},d="wrapper";function p(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"getting-started"},"Getting Started"),(0,i.kt)("p",null,"Welcome to the DevOps with Docker course! This course is designed to be completed sequentially, from start to finish. Each part builds on the previous one, so it's important to read the material carefully and complete the exercises to develop the necessary skills."),(0,i.kt)("p",null,"To pass the course, you will need to complete all of the exercises. However, one exercise can be skipped per part, except for the exercises marked as mandatory. The mandatory exercises cannot be skipped."),(0,i.kt)("p",null,"The exercises are designed to reinforce the material covered in each part and are placed at strategic points in the course to ensure that you have learned the necessary skills before attempting each exercise. You can complete the exercises at your own pace, and there is no deadline for submission outside of the last date when the entire course ends."),(0,i.kt)("p",null,"When submitting your exercises, please follow the instructions provided in the course material. Exercises should be submitted in a specific format, which will be outlined in the instructions for each exercise."),(0,i.kt)("p",null,"We hope that you enjoy the course and find it informative and engaging. Good luck!"),(0,i.kt)("h3",{id:"prerequisites"},"Prerequisites"),(0,i.kt)("p",null,"The course is suitable for anyone interested in Docker or containerization and has at least some experience with the Linux command line. It also helps if you have some experience in web development."),(0,i.kt)("h3",{id:"updating-of-the-material-for-the-2024-edition"},"Updating of the material for the 2024 edition"),(0,i.kt)("p",null,"The 2024 edition of the course starts officially on 11th March. The material is currently being updated. At the time of writing (11th March) the following parts have already been updated"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Part 1"),(0,i.kt)("li",{parentName:"ul"},"Part 2")),(0,i.kt)("p",null,"You may continue already beyond the updated material but beware, there might be some outdated content!"),(0,i.kt)("h3",{id:"about-different-architectures-and-contributing"},"About different architectures and contributing"),(0,i.kt)("p",null,"Please note that while Docker runs on all major operating systems and even on ARM architecture, this course material may not cover platform-specific details for all operating systems. However, we've had students successfully complete the course using a variety of machines and operating systems."),(0,i.kt)("p",null,"If you encounter any issues while working through the course material on your particular system, we recommend consulting the Docker documentation or seeking help on the course forums. Our community is here to support you and help you succeed in the course!"),(0,i.kt)("p",null,"We welcome contributions to the course material from students and other members of the DevOps community! If you notice any mistakes, typos, or errors in the material, please consider submitting a pull request to the course repository on GitHub."),(0,i.kt)("p",null,"Thank you in advance for your contributions to this open source project!"),(0,i.kt)("h3",{id:"grading"},"Grading"),(0,i.kt)("p",null,"Passing this course requires you to do the exercises for each part. This means generally every exercise, but you are allowed to skip one non-mandatory exercise in each part. Some of the exercises are mandatory and can not be skipped."),(0,i.kt)("p",null,"This course is worth 1-3 credits depending on the completed parts. Completing part 1 gives you 1 credit. Completing parts 1 and 2 is worth 2 credits. Completing all of the parts will grant you 3 credits."),(0,i.kt)("p",null,"There are additional instructions for completion after each part and at the end of this page."),(0,i.kt)("h3",{id:"learning-objectives"},"Learning objectives"),(0,i.kt)("p",null,"Part 1: DevOps with Docker (",(0,i.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/toteutus/otm-4bd45ab8-8b23-4973-a918-a6b6f7bbb347/TKT21036"},"TKT21036"),")"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Understand the fundamental concepts of Docker, including images and containers."),(0,i.kt)("li",{parentName:"ul"},"Learn how to build Docker images for existing projects and run them."),(0,i.kt)("li",{parentName:"ul"},"Understand how Docker can simplify the development process.")),(0,i.kt)("p",null,"Part 2: DevOps with Docker: docker-compose (",(0,i.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/toteutus/otm-c73ef1c6-8fb0-42e8-9052-ef59b01cb409/TKT21037"},"TKT21037"),")"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Learn how to manage complex multi-container applications with Docker Compose."),(0,i.kt)("li",{parentName:"ul"},"Understand the role of Docker Compose in container orchestration"),(0,i.kt)("li",{parentName:"ul"},"Practice deploying and managing real-world applications using Docker Compose.")),(0,i.kt)("p",null,"Part 3: DevOps with Docker: security and optimization (",(0,i.kt)("a",{parentName:"p",href:"https://studies.helsinki.fi/kurssit/opintojakso/hy-CU-142971306-2020-08-01/TKT21038"},"TKT21038"),")"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Learn how to optimize Docker images for production, including reducing image size and improving security."),(0,i.kt)("li",{parentName:"ul"},"Understand the limitations of using Docker Compose in production environments and the need for more advanced orchestration tools."),(0,i.kt)("li",{parentName:"ul"},"Explore alternative container orchestration solutions, including Kubernetes.")),(0,i.kt)("h3",{id:"where-to-find-information-about-the-course"},"Where to find information about the course?"),(0,i.kt)("p",null,"All of the details you need to complete the course should be found on this page. If something is missing or unclear after reading this page, please contact ",(0,i.kt)("a",{parentName:"p",href:"mailto:matti.luukkainen@helsinki.fi"},"matti.luukkainen@helsinki.fi")," or get in touch through Discord."),(0,i.kt)("h3",{id:"discord"},"Discord"),(0,i.kt)("p",null,"This course has a Discord group where we discuss everything about the course. Support is available almost 24/7, with the discussion being in both English and Finnish."),(0,i.kt)("p",null,"Join our discord group ",(0,i.kt)("a",{parentName:"p",href:"https://study.cs.helsinki.fi/discord/join/docker"},"here"),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"All")," inappropriate, degrading or discriminating comments on the channel are prohibited and will lead to action taken against the commenter."),(0,i.kt)("h1",{id:"warning-before-installing-docker"},"Warning: Before installing Docker"),(0,i.kt)("p",null,"Containers leverage the power of your own operating system. As such ",(0,i.kt)("strong",{parentName:"p"},"by default")," any containerized application, or user who has external access to your container, would have super user privileges to your computer."),(0,i.kt)("p",null,"I will try my best to alert you of potential risks as we encounter them, but due to the structure of the course we will focus on security in part 3."),(0,i.kt)("p",null,"Please keep this in mind as you move through the installation and exercises. If you ever feel unsure about what you're doing, come to the Discord channel and have a chat with us."),(0,i.kt)("h2",{id:"installing-docker"},"Installing Docker"),(0,i.kt)("p",null,"Use the official documentation to find download instructions for docker-ce for the platform of your choice:"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://docs.docker.com/install/linux/docker-ce/ubuntu/"},"Ubuntu")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://docs.docker.com/docker-for-mac/install/"},"MacOS")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://docs.docker.com/docker-for-windows/install/"},"Windows")),(0,i.kt)("p",null,"Confirm that Docker installed correctly by opening a terminal and running ",(0,i.kt)("inlineCode",{parentName:"p"},"docker -v")," to see the installed version."),(0,i.kt)("admonition",{title:"Docker group",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"To avoid writing sudos you may consider ",(0,i.kt)("a",{parentName:"p",href:"https://docs.docker.com/install/linux/linux-postinstall/"},"adding yourself to docker group")),(0,i.kt)("p",{parentName:"admonition"},"Keep in mind that if you do so, you can now run containers without sudo and containers give you super user access to the computer.")),(0,i.kt)("h2",{id:"deadline"},"Deadline"),(0,i.kt)("p",null,"The sign up for ECTS credits and the course ends 16.6.2024! After that course is locked and submissions can no longer be made or credits earned. As the certificate is received through submissions, you have to submit everything before the course ends. More details under completion and after each part."),(0,i.kt)("h2",{id:"general-guidance"},"General guidance"),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"Do not alter the code of the projects, unless by pull-requests to the original projects")),(0,i.kt)("p",null,"You do not need to touch Ruby, Java, Javascript or Python code during this course. You may have to read their error messages."),(0,i.kt)("p",null,"Visit the Discord channel if you are stuck!"),(0,i.kt)("h2",{id:"how-to-submit-the-exercises"},"How to submit the exercises"),(0,i.kt)("p",null,"Make a repository to GitHub and publish your solutions in clearly ordered files / folders. If you need help publishing using Git you should refer to their ",(0,i.kt)("a",{parentName:"p",href:"https://guides.github.com/activities/hello-world/"},"guide"),". Make sure that the repository is available to us, either by using a public repository or a private repository and adding Jakousa and mluukkai as collaborators."),(0,i.kt)("p",null,"Most of the exercises will be focused on a Dockerfile and/or docker-compose.yml. In those cases, submitting the file is enough. In other cases, a picture or copy-paste from your command line or a link to Docker Hub and/or project inside the repository is enough. For the command line exercises at start the command ",(0,i.kt)("a",{parentName:"p",href:"https://linux.die.net/man/1/script"},"script")," may be helpful."),(0,i.kt)("p",null,"Because the course exercises are designed to build upon each other, it's more important that you document the exercises for yourself. We will be looking at the submissions of the later exercises as they are more demanding."),(0,i.kt)("p",null,"When you have completed a part, use the ",(0,i.kt)("a",{parentName:"p",href:"https://studies.cs.helsinki.fi/stats/courses/docker2024"},"submission application")," to mark your exercises. You can ",(0,i.kt)("strong",{parentName:"p"},"not")," edit a submission, so make sure you have completed enough exercises for a part before submitting."),(0,i.kt)("h2",{id:"completing"},"Completing"),(0,i.kt)("p",null,"The certificate is available from the small icon beneath your submissions!"),(0,i.kt)("p",null,'After you have returned all of the required exercises and wish to end your course completion and want the ECTS credits press the following button in the submission application (ignore the message about an "exam" as there is no exam in this course):'),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Incomplete course",src:o(6795).Z,width:"874",height:"188"})),(0,i.kt)("p",null,'After that, double-check that the application has the message "Course marked as completed" and the date. If the date is not visible, we have not been notified.'),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Completed course",src:o(38).Z,width:"482",height:"469"})))}p.isMDXComponent=!0},38:(e,t,o)=>{o.d(t,{Z:()=>r});const r=o.p+"assets/images/completed_course-1c9c27f6aefc0214cb0b511b6358980c.png"},6795:(e,t,o)=>{o.d(t,{Z:()=>r});const r=o.p+"assets/images/incomplete_course-8a93bc802c0307b99b884cb844e664ff.png"}}]); \ No newline at end of file diff --git a/assets/js/main.9ccac223.js b/assets/js/main.a9117bc5.js similarity index 99% rename from assets/js/main.9ccac223.js rename to assets/js/main.a9117bc5.js index bad7c8e5..785d70dc 100644 --- a/assets/js/main.9ccac223.js +++ b/assets/js/main.a9117bc5.js @@ -1,2 +1,2 @@ -/*! For license information please see main.9ccac223.js.LICENSE.txt */ -(self.webpackChunk=self.webpackChunk||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),l=n(6887);const s={"0480b142":[()=>n.e(836).then(n.bind(n,3584)),"@site/docs/faq.md",3584],"06d0a36c":[()=>n.e(366).then(n.bind(n,2403)),"@site/docs/part-2/section-3.md",2403],"0760ddad":[()=>n.e(48).then(n.bind(n,1389)),"@site/docs/part-1/section-4.md",1389],"0da1f8d4":[()=>n.e(139).then(n.bind(n,3071)),"@site/docs/part-2/section-4.md",3071],"10e9c4ba":[()=>n.e(862).then(n.bind(n,8494)),"@site/docs/part-1/section-5.md",8494],"14eb3368":[()=>Promise.all([n.e(532),n.e(817)]).then(n.bind(n,4228)),"@theme/DocCategoryGeneratedIndexPage",4228],"152729e2":[()=>n.e(943).then(n.bind(n,5683)),"@site/docs/part-3/section-6.md",5683],17896441:[()=>Promise.all([n.e(532),n.e(918)]).then(n.bind(n,5824)),"@theme/DocItem",5824],"18ba09e8":[()=>n.e(657).then(n.bind(n,3375)),"@site/docs/credits.md",3375],"1be78505":[()=>Promise.all([n.e(532),n.e(514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"2d61a0bd":[()=>n.e(906).then(n.t.bind(n,4858,19)),"~docs/default/category-materialsidebar-category-part-3-0b8.json",4858],"3006da3d":[()=>n.e(654).then(n.bind(n,1851)),"@site/docs/part-2/section-5.md",1851],"3358ea11":[()=>n.e(540).then(n.bind(n,7506)),"@site/docs/part-2/section-2.md",7506],"3496bbe8":[()=>n.e(882).then(n.bind(n,9999)),"@site/docs/part-3/section-3.md",9999],"3669c705":[()=>n.e(768).then(n.bind(n,5146)),"@site/docs/part-3/index.md",5146],"4172bbd4":[()=>n.e(501).then(n.bind(n,154)),"@site/docs/part-1/section-1.md",154],"44a2208c":[()=>n.e(328).then(n.t.bind(n,6031,19)),"~docs/default/category-materialsidebar-category-part-2-e23.json",6031],"5e47b935":[()=>n.e(948).then(n.bind(n,3906)),"@site/docs/part-1/section-2.md",3906],"71951c43":[()=>n.e(93).then(n.bind(n,8660)),"@site/docs/part-1/section-6.md",8660],"85ab0e2f":[()=>n.e(97).then(n.bind(n,7544)),"@site/docs/part-3/section-2.md",7544],"88cfbd19":[()=>n.e(935).then(n.bind(n,9524)),"@site/docs/part-3/section-4.md",9524],"8c5badca":[()=>n.e(847).then(n.t.bind(n,4245,19)),"~docs/default/category-materialsidebar-category-part-1-c10.json",4245],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"9ed8673f":[()=>n.e(261).then(n.t.bind(n,3769,19)),"/home/runner/work/docker-hy.github.io/docker-hy.github.io/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],b99b65ed:[()=>n.e(221).then(n.bind(n,888)),"@site/docs/part-1/index.md",888],c6640654:[()=>n.e(745).then(n.bind(n,383)),"@site/docs/part-3/section-5.md",383],cca8f319:[()=>n.e(451).then(n.bind(n,320)),"@site/docs/part-2/index.md",320],d589d3a7:[()=>n.e(162).then(n.bind(n,9390)),"@site/docs/getting-started.md",9390],dbf6ab84:[()=>n.e(258).then(n.bind(n,3469)),"@site/docs/part-3/section-1.md",3469],eea426ee:[()=>n.e(538).then(n.bind(n,7530)),"@site/docs/part-2/section-1.md",7530],f1c60e00:[()=>n.e(33).then(n.bind(n,6920)),"@site/docs/part-1/section-3.md",6920],f8409a7e:[()=>Promise.all([n.e(532),n.e(206)]).then(n.bind(n,3509)),"@site/docs/intro.mdx",3509],ff03218c:[()=>n.e(632).then(n.bind(n,6093)),"@site/docs/part-1/section-7.md",6093]};function u(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var c=n(9670),d=n(226);function f(e,t){if("*"===e)return i()({loading:u,loader:()=>n.e(972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=l[`${e}-${t}`],f={},p=[],m=[],h=(0,c.Z)(o);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=s[n];r&&(f[t]=r[0],p.push(r[1]),m.push(r[2]))})),i().Map({loading:u,loader:f,modules:p,webpack:()=>m,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const l=n.split(".");l.slice(0,-1).forEach((e=>{o=o[e]})),o[l[l.length-1]]=a}));const l=i.__comp;delete i.__comp;const s=i.__context;return delete i.__context,r.createElement(d.z,{value:s},r.createElement(l,(0,a.Z)({},i,n)))}})}const p=[{path:"/",component:f("/","ca0"),routes:[{path:"/",component:f("/","a21"),exact:!0,sidebar:"materialSidebar"},{path:"/category/part-1",component:f("/category/part-1","31f"),exact:!0,sidebar:"materialSidebar"},{path:"/category/part-2",component:f("/category/part-2","5c2"),exact:!0,sidebar:"materialSidebar"},{path:"/category/part-3",component:f("/category/part-3","395"),exact:!0,sidebar:"materialSidebar"},{path:"/credits",component:f("/credits","f75"),exact:!0,sidebar:"materialSidebar"},{path:"/faq",component:f("/faq","2d3"),exact:!0,sidebar:"materialSidebar"},{path:"/getting-started",component:f("/getting-started","2d9"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/",component:f("/part-1/","29b"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-1",component:f("/part-1/section-1","53c"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-2",component:f("/part-1/section-2","0ad"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-3",component:f("/part-1/section-3","092"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-4",component:f("/part-1/section-4","879"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-5",component:f("/part-1/section-5","5f5"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-6",component:f("/part-1/section-6","d3b"),exact:!0,sidebar:"materialSidebar"},{path:"/part-1/section-7",component:f("/part-1/section-7","ee1"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/",component:f("/part-2/","97f"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/section-1",component:f("/part-2/section-1","44d"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/section-2",component:f("/part-2/section-2","521"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/section-3",component:f("/part-2/section-3","a8e"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/section-4",component:f("/part-2/section-4","d1f"),exact:!0,sidebar:"materialSidebar"},{path:"/part-2/section-5",component:f("/part-2/section-5","a8a"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/",component:f("/part-3/","bfe"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-1",component:f("/part-3/section-1","03d"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-2",component:f("/part-3/section-2","edf"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-3",component:f("/part-3/section-3","bf2"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-4",component:f("/part-3/section-4","89f"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-5",component:f("/part-3/section-5","10f"),exact:!0,sidebar:"materialSidebar"},{path:"/part-3/section-6",component:f("/part-3/section-6","1b6"),exact:!0,sidebar:"materialSidebar"}]},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),l=n(412);const s=[n(2497),n(3310),n(8320),n(2295)];var u=n(723),c=n(6550),d=n(8790);function f(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var p=n(7462),m=n(5742),h=n(2263),g=n(4996),b=n(6668),v=n(1944),y=n(4711),w=n(9727),k=n(3320),E=n(197);function S(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,h.Z)(),n=(0,y.l)();return r.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function x(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),a=function(){const{siteConfig:{url:e}}=(0,h.Z)(),{pathname:t}=(0,c.TH)();return e+(0,g.Z)(t)}(),o=t?`${n}${t}`:a;return r.createElement(m.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function C(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,b.L)();return r.createElement(r.Fragment,null,r.createElement(m.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(v.d,{image:n}),r.createElement(x,null),r.createElement(S,null),r.createElement(E.Z,{tag:k.HX,locale:e}),r.createElement(m.Z,null,t.map(((e,t)=>r.createElement("meta",(0,p.Z)({key:t},e))))))}const _=new Map;function T(e){if(_.has(e.pathname))return{...e,pathname:_.get(e.pathname)};if((0,d.f)(u.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return _.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return _.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),L=n(8940);function R(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:a}),R("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(u.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class P extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=l.Z.canUseDOM?R("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=R("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(N,{previousLocation:this.previousLocation,location:t},r.createElement(c.AW,{location:t,render:()=>e}))}}const D=P,I="docusaurus-base-url-issue-banner-container",M="docusaurus-base-url-issue-banner",F="docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function j(e){return`\nwindow['${B}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${B}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${I}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{window[B]=!1}),[]),r.createElement(r.Fragment,null,!l.Z.canUseDOM&&r.createElement(m.Z,null,r.createElement("script",null,j(e))),r.createElement("div",{id:I}))}function U(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.Z)(),{pathname:n}=(0,c.TH)();return t&&n===e?r.createElement(z,null):null}function $(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,h.Z)(),i=(0,g.Z)(e),{htmlLang:l,direction:s}=o[a];return r.createElement(m.Z,null,r.createElement("html",{lang:l,dir:s}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var q=n(4763);function H(){const e=(0,d.H)(u.Z),t=(0,c.TH)();return r.createElement(q.Z,null,r.createElement(L.M,null,r.createElement(A.t,null,r.createElement(f,null,r.createElement($,null),r.createElement(C,null),r.createElement(U,null),r.createElement(D,{location:T(t)},e)))))}var G=n(6887);const Z=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var V=n(9670);const W=new Set,Y=new Set,K=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,Q={prefetch(e){if(!(e=>!K()&&!Y.has(e)&&!W.has(e))(e))return!1;W.add(e);const t=(0,d.f)(u.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(G).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,V.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Z(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!K()&&!Y.has(e))(e)&&(Y.add(e),O(e))},X=Object.freeze(Q);if(l.Z.canUseDOM){window.docusaurus=X;const e=a.hydrate;O(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(H,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>c,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-lunr-search":{"default":{"fileNames":{"searchDoc":"search-doc-1710279153302.json","lunrIndex":"lunr-index-1710279153302.json"}}},"docusaurus-plugin-content-docs":{"default":{"path":"/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/","mainDocId":"intro","docs":[{"id":"credits","path":"/credits","sidebar":"materialSidebar"},{"id":"faq","path":"/faq","sidebar":"materialSidebar"},{"id":"getting-started","path":"/getting-started","sidebar":"materialSidebar"},{"id":"intro","path":"/","sidebar":"materialSidebar"},{"id":"part-1/index","path":"/part-1/","sidebar":"materialSidebar"},{"id":"part-1/section-1","path":"/part-1/section-1","sidebar":"materialSidebar"},{"id":"part-1/section-2","path":"/part-1/section-2","sidebar":"materialSidebar"},{"id":"part-1/section-3","path":"/part-1/section-3","sidebar":"materialSidebar"},{"id":"part-1/section-4","path":"/part-1/section-4","sidebar":"materialSidebar"},{"id":"part-1/section-5","path":"/part-1/section-5","sidebar":"materialSidebar"},{"id":"part-1/section-6","path":"/part-1/section-6","sidebar":"materialSidebar"},{"id":"part-1/section-7","path":"/part-1/section-7","sidebar":"materialSidebar"},{"id":"part-2/index","path":"/part-2/","sidebar":"materialSidebar"},{"id":"part-2/section-1","path":"/part-2/section-1","sidebar":"materialSidebar"},{"id":"part-2/section-2","path":"/part-2/section-2","sidebar":"materialSidebar"},{"id":"part-2/section-3","path":"/part-2/section-3","sidebar":"materialSidebar"},{"id":"part-2/section-4","path":"/part-2/section-4","sidebar":"materialSidebar"},{"id":"part-2/section-5","path":"/part-2/section-5","sidebar":"materialSidebar"},{"id":"part-3/index","path":"/part-3/","sidebar":"materialSidebar"},{"id":"part-3/section-1","path":"/part-3/section-1","sidebar":"materialSidebar"},{"id":"part-3/section-2","path":"/part-3/section-2","sidebar":"materialSidebar"},{"id":"part-3/section-3","path":"/part-3/section-3","sidebar":"materialSidebar"},{"id":"part-3/section-4","path":"/part-3/section-4","sidebar":"materialSidebar"},{"id":"part-3/section-5","path":"/part-3/section-5","sidebar":"materialSidebar"},{"id":"part-3/section-6","path":"/part-3/section-6","sidebar":"materialSidebar"},{"id":"/category/part-1","path":"/category/part-1","sidebar":"materialSidebar"},{"id":"/category/part-2","path":"/category/part-2","sidebar":"materialSidebar"},{"id":"/category/part-3","path":"/category/part-3","sidebar":"materialSidebar"}],"draftIds":[],"sidebars":{"materialSidebar":{"link":{"path":"/","label":"intro"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var l=n(7529);const s=JSON.parse('{"docusaurusVersion":"2.3.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.3.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.3.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.3.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.3.1"},"docusaurus-lunr-search":{"type":"package","name":"docusaurus-lunr-search","version":"2.3.2"}}}'),u={siteConfig:a.Z,siteMetadata:s,globalData:o,i18n:i,codeTranslations:l},c=r.createContext(u);function d(e){let{children:t}=e;return r.createElement(c.Provider,{value:u},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7294),a=n(412),o=n(5742),i=n(4510);function l(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",height:"50vh",width:"100%",fontSize:"20px"}},r.createElement("h1",null,"This page crashed."),r.createElement("p",null,t.message),r.createElement("button",{type:"button",onClick:n},"Try again"))}function s(e){let{error:t,tryAgain:n}=e;return r.createElement(c,{fallback:()=>r.createElement(l,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(i.Z,null,r.createElement(l,{error:t,tryAgain:n})))}const u=e=>r.createElement(s,e);class c extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??u)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>h});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),l=n(2263),s=n(3919),u=n(412);const c=a.createContext({collectLink:()=>{}}),d=()=>(0,a.useContext)(c);var f=n(4996);const p=e=>e.startsWith("/");function m(e,t){let{isNavLink:n,to:c,href:m,activeClassName:h,isActive:g,"data-noBrokenLinkCheck":b,autoAddBaseUrl:v=!0,...y}=e;const{siteConfig:{trailingSlash:w,baseUrl:k}}=(0,l.Z)(),{withBaseUrl:E}=(0,f.C)(),S=d(),x=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>x.current));const C=c||m;const _=(0,s.Z)(C),T=C?.replace("pathname://","");let A=void 0!==T?(L=T,v&&p(L)?E(L):L):void 0;var L;A&&_&&(A=(0,i.applyTrailingSlash)(A,{trailingSlash:w,baseUrl:k}));const R=(0,a.useRef)(!1),N=n?o.OL:o.rU,O=u.Z.canUseIntersectionObserver,P=(0,a.useRef)(),D=()=>{R.current||null==A||(window.docusaurus.preload(A),R.current=!0)};(0,a.useEffect)((()=>(!O&&_&&null!=A&&window.docusaurus.prefetch(A),()=>{O&&P.current&&P.current.disconnect()})),[P,A,O,_]);const I=A?.startsWith("#")??!1,M=!A||!_||I;return M||b||S.collectLink(A),M?a.createElement("a",(0,r.Z)({ref:x,href:A},C&&!_&&{target:"_blank",rel:"noopener noreferrer"},y)):a.createElement(N,(0,r.Z)({},y,{onMouseEnter:D,onTouchStart:D,innerRef:e=>{x.current=e,O&&e&&_&&(P.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(P.current.unobserve(e),P.current.disconnect(),null!=A&&window.docusaurus.prefetch(A))}))})),P.current.observe(e))},to:A},n&&{isActive:g,activeClassName:h}))}const h=a.forwardRef(m)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>s,I:()=>l});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function s(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const l=i({message:t,id:n});return r.createElement(r.Fragment,null,a(l,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>l});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const l=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+l:l}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function l(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},8084:(e,t,n)=>{"use strict";n.d(t,{OD:()=>o,eZ:()=>i});var r=n(2263),a=n(9935);function o(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}function i(e,t,n){void 0===t&&(t=a.m),void 0===n&&(n={});const r=o(e),i=r?.[t];if(!i&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return i}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){const t=".",n={};return function e(a,o){Object.entries(a).forEach((a=>{let[i,l]=a;const s=o?`${o}${t}${i}`:i;r(l)?e(l,s):n[s]=l}))}(e),n}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},4104:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>p,gA:()=>c,_r:()=>s,Jo:()=>m,zh:()=>u,yW:()=>f,gB:()=>d});var r=n(6550),a=n(8084);const o=e=>e.versions.find((e=>e.isLast));function i(e,t){const n=function(e,t){const n=o(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const l={},s=()=>(0,a.OD)("docusaurus-plugin-content-docs")??l,u=e=>(0,a.eZ)("docusaurus-plugin-content-docs",e,{failfast:!0});function c(e){void 0===e&&(e={});const t=s(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function d(e){return u(e).versions}function f(e){const t=u(e);return o(t)}function p(e){const t=u(e),{pathname:n}=(0,r.TH)();return i(t,n)}function m(e){const t=u(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=o(e);return{latestDocSuggestion:i(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.Z,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a={iconExternalLink:"iconExternalLink_nPIU"};function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a.iconExternalLink},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},4510:(e,t,n)=>{"use strict";n.d(t,{Z:()=>ut});var r=n(7294),a=n(6010),o=n(4763),i=n(1944),l=n(7462),s=n(6550),u=n(5999),c=n(5936);const d="docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,s.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,c.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,u.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:a}=p();return r.createElement("div",{ref:n,role:"region","aria-label":m},r.createElement("a",(0,l.Z)({},e,{href:`#${d}`,onClick:a}),t))}var g=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return r.createElement(h,{className:v.skipToContent})}var w=n(6668),k=n(9689);function E(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...s}=e;return r.createElement("svg",(0,l.Z)({viewBox:"0 0 15 15",width:t,height:n},s),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const S={closeButton:"closeButton_CVFx"};function x(e){return r.createElement("button",(0,l.Z)({type:"button","aria-label":(0,u.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",S.closeButton,e.className)}),r.createElement(E,{width:14,height:14,strokeWidth:3.1}))}const C={content:"content_knG7"};function _(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return r.createElement("div",(0,l.Z)({},e,{className:(0,a.Z)(C.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function A(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,k.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T.announcementBar,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:T.announcementBarPlaceholder}),r.createElement(_,{className:T.announcementBarContent}),i&&r.createElement(x,{onClick:n,className:T.announcementBarClose}))}var L=n(2961),R=n(2466);var N=n(902),O=n(3102);const P=r.createContext(null);function D(e){let{children:t}=e;const n=function(){const e=(0,L.e)(),t=(0,O.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,N.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(P.Provider,{value:n},t)}function I(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function M(){const e=(0,r.useContext)(P);if(!e)throw new N.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,O.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:I(o)})),[a,o,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=M();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var B=n(2949),j=n(2389);function z(e){return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function U(e){return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function q(e){let{className:t,value:n,onChange:o}=e;const i=(0,j.Z)(),l=(0,u.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===n?(0,u.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,u.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)($.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",$.toggleButton,!i&&$.toggleButtonDisabled),type:"button",onClick:()=>o("dark"===n?"light":"dark"),disabled:!i,title:l,"aria-label":l,"aria-live":"polite"},r.createElement(z,{className:(0,a.Z)($.toggleIcon,$.lightToggleIcon)}),r.createElement(U,{className:(0,a.Z)($.toggleIcon,$.darkToggleIcon)})))}const H=r.memo(q);function G(e){let{className:t}=e;const n=(0,w.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:o}=(0,B.I)();return n?null:r.createElement(H,{className:t,value:a,onChange:o})}var Z=n(1327);function V(){return r.createElement(Z.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function W(){const e=(0,L.e)();return r.createElement("button",{type:"button","aria-label":(0,u.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(E,{color:"var(--ifm-color-emphasis-600)"}))}function Y(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(V,null),r.createElement(G,{className:"margin-right--md"}),r.createElement(W,null))}var K=n(9960),Q=n(4996),X=n(3919);function J(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var ee=n(9471);function te(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:s,isDropdownLink:u,prependBaseUrlToHref:c,...d}=e;const f=(0,Q.Z)(a),p=(0,Q.Z)(t),m=(0,Q.Z)(o,{forcePrependBaseUrl:!0}),h=i&&o&&!(0,X.Z)(o),g=s?{dangerouslySetInnerHTML:{__html:s}}:{children:r.createElement(r.Fragment,null,i,h&&r.createElement(ee.Z,u&&{width:12,height:12}))};return o?r.createElement(K.Z,(0,l.Z)({href:c?m:o},d,g)):r.createElement(K.Z,(0,l.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?J(n,t.pathname):t.pathname.startsWith(p)},d,g))}function ne(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(te,(0,l.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function re(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(te,(0,l.Z)({className:(0,a.Z)("menu__link",t)},o)))}function ae(e){let{mobile:t=!1,position:n,...a}=e;const o=t?re:ne;return r.createElement(o,(0,l.Z)({},a,{activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var oe=n(6043),ie=n(8596),le=n(2263);function se(e,t){return e.some((e=>function(e,t){return!!(0,ie.Mg)(e.to,t)||!!J(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:i,...s}=e;const u=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{u.current&&!u.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e)}}),[u]),r.createElement("div",{ref:u,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c})},r.createElement(te,(0,l.Z)({"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,a.Z)("navbar__link",o)},s,{onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))}}),s.children??s.label),r.createElement("ul",{className:"dropdown__menu"},t.map(((e,n)=>r.createElement(Te,(0,l.Z)({isDropdownItem:!0,onKeyDown:e=>{if(n===t.length-1&&"Tab"===e.key){e.preventDefault(),d(!1);const t=u.current.nextElementSibling;if(t){(t instanceof HTMLAnchorElement?t:t.querySelector("a")).focus()}}},activeClassName:"dropdown__link--active"},e,{key:n}))))))}function ce(e){let{items:t,className:n,position:o,onClick:i,...u}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=se(t,c),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,oe.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":f})},r.createElement(te,(0,l.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},u,{onClick:e=>{e.preventDefault(),p()}}),u.children??u.label),r.createElement(oe.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>r.createElement(Te,(0,l.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function de(e){let{mobile:t=!1,...n}=e;const a=t?ce:ue;return r.createElement(a,n)}var fe=n(4711);function pe(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const me={iconLanguage:"iconLanguage_nlXk"};var he=n(4184),ge=n.n(he),be=n(8084);const ve=e=>{const t=(0,r.useRef)(!1),a=(0,r.useRef)(null),[o,i]=(0,r.useState)(!1),l=(0,s.k6)(),{siteConfig:u={}}=(0,le.Z)(),c=(0,j.Z)(),{baseUrl:d}=u,f=(0,be.eZ)("docusaurus-lunr-search"),p=()=>{t.current||(Promise.all([fetch(`${d}${f.fileNames.searchDoc}`).then((e=>e.json())),fetch(`${d}${f.fileNames.lunrIndex}`).then((e=>e.json())),Promise.all([n.e(878),n.e(339)]).then(n.bind(n,894)),Promise.all([n.e(532),n.e(343)]).then(n.bind(n,3343))]).then((e=>{let[t,n,{default:r}]=e;0!==t.length&&(((e,t,n)=>{new n({searchDocs:e,searchIndex:t,baseUrl:d,inputSelector:"#search_input_react",handleSelected:(e,t,n)=>{const r=n.url||"/";document.createElement("a").href=r,l.push(r)}})})(t,n,r),i(!0))})),t.current=!0)},m=(0,r.useCallback)((t=>{a.current.contains(t.target)||a.current.focus(),e.handleSearchBarToggle&&e.handleSearchBarToggle(!e.isSearchBarExpanded)}),[e.isSearchBarExpanded]);return c&&p(),r.createElement("div",{className:"navbar__search",key:"search-box"},r.createElement("span",{"aria-label":"expand searchbar",role:"button",className:ge()("search-icon",{"search-icon-hidden":e.isSearchBarExpanded}),onClick:m,onKeyDown:m,tabIndex:0}),r.createElement("input",{id:"search_input_react",type:"search",placeholder:o?"Search":"Loading...","aria-label":"Search",className:ge()("navbar__search-input",{"search-bar-expanded":e.isSearchBarExpanded},{"search-bar":!e.isSearchBarExpanded}),onClick:p,onMouseOver:p,onFocus:m,onBlur:m,ref:a,disabled:!o}))},ye={searchBox:"searchBox_ZlJk"};function we(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,ye.searchBox)},t)}var ke=n(4104),Ee=n(2802);const Se=e=>e.docs.find((t=>t.id===e.mainDocId));var xe=n(373);const Ce=e=>e.docs.find((t=>t.id===e.mainDocId));const _e={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.Z)(),f=(0,fe.l)(),{search:p,hash:m}=(0,s.TH)(),h=[...n,...c.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],g=t?(0,u.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(de,(0,l.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(pe,{className:me.iconLanguage}),g),items:h}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(we,{className:n},r.createElement(ve,null))},dropdown:de,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const l=i?"li":"div";return r.createElement(l,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ke.Iw)(a),s=(0,Ee.vY)(t,a);return null===s?null:r.createElement(ae,(0,l.Z)({exact:!0},o,{isActive:()=>i?.path===s.path||!!i?.sidebar&&i.sidebar===s.sidebar,label:n??s.id,to:s.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ke.Iw)(a),s=(0,Ee.oz)(t,a).link;if(!s)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return r.createElement(ae,(0,l.Z)({exact:!0},o,{isActive:()=>i?.sidebar===t,label:n??s.label,to:s.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,Ee.lO)(a)[0],s=t??i.label,u=n??Se(i).path;return r.createElement(ae,(0,l.Z)({},o,{label:s,to:u}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...c}=e;const{search:d,hash:f}=(0,s.TH)(),p=(0,ke.Iw)(n),m=(0,ke.gB)(n),{savePreferredVersionName:h}=(0,xe.J)(n),g=[...o,...m.map((e=>{const t=p.alternateDocVersions[e.name]??Ce(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...i],b=(0,Ee.lO)(n)[0],v=t&&g.length>1?(0,u.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&g.length>1?void 0:Ce(b).path;return g.length<=1?r.createElement(ae,(0,l.Z)({},c,{mobile:t,label:v,to:y,isActive:a?()=>!1:void 0})):r.createElement(de,(0,l.Z)({},c,{mobile:t,label:v,to:y,items:g,isActive:a?()=>!1:void 0}))}};function Te(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=_e[a];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(o,n)}function Ae(){const e=(0,L.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(Te,(0,l.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Le(e){return r.createElement("button",(0,l.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(u.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Re(){const e=0===(0,w.L)().navbar.items.length,t=M();return r.createElement(r.Fragment,null,!e&&r.createElement(Le,{onClick:()=>t.hide()}),t.content)}function Ne(){const e=(0,L.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(F,{header:r.createElement(Y,null),primaryMenu:r.createElement(Ae,null),secondaryMenu:r.createElement(Re,null)}):null}const Oe={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Pe(e){return r.createElement("div",(0,l.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function De(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,L.e)(),{navbarRef:l,isNavbarVisible:s}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,R.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=l?n(!1):i+u{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:l,"aria-label":(0,u.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Oe.navbarHideable,!s&&Oe.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Pe,{onClick:i.toggle}),r.createElement(Ne,null))}const Ie="right";function Me(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,l.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function Fe(){const{toggle:e,shown:t}=(0,L.e)();return r.createElement("button",{onClick:e,"aria-label":(0,u.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(Me,null))}const Be={colorModeToggle:"colorModeToggle_DEke"};function je(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(Te,(0,l.Z)({},e,{key:t})))))}function ze(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function Ue(){const e=(0,L.e)(),t=(0,w.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??Ie)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(ze,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(Fe,null),r.createElement(V,null),r.createElement(je,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(je,{items:a}),r.createElement(G,{className:Be.colorModeToggle}),!o&&r.createElement(we,null,r.createElement(ve,null)))})}function $e(){return r.createElement(De,null,r.createElement(Ue,null))}function qe(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...s}=t,u=(0,Q.Z)(n),c=(0,Q.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(K.Z,(0,l.Z)({className:"footer__link-item"},a?{href:i?c:a}:{to:u},s),o,a&&!(0,X.Z)(a)&&r.createElement(ee.Z,null))}function He(e){let{item:t}=e;return t.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement("li",{key:t.href??t.to,className:"footer__item"},r.createElement(qe,{item:t}))}function Ge(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(He,{key:t,item:e})))))}function Ze(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(Ge,{key:t,column:e}))))}function Ve(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function We(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(qe,{item:t})}function Ye(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(We,{item:e}),t.length!==n+1&&r.createElement(Ve,null))))))}function Ke(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(Ze,{columns:t}):r.createElement(Ye,{links:t})}var Qe=n(941);const Xe={footerLogoLink:"footerLogoLink_BH7S"};function Je(e){let{logo:t}=e;const{withBaseUrl:n}=(0,Q.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(Qe.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function et(e){let{logo:t}=e;return t.href?r.createElement(K.Z,{href:t.href,className:Xe.footerLogoLink,target:t.target},r.createElement(Je,{logo:t})):r.createElement(Je,{logo:t})}function tt(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function nt(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--center"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function rt(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(nt,{style:o,links:n&&n.length>0&&r.createElement(Ke,{links:n}),logo:a&&r.createElement(et,{logo:a}),copyright:t&&r.createElement(tt,{copyright:t})})}const at=r.memo(rt),ot=(0,N.Qc)([B.S,k.pl,R.OC,xe.L5,i.VC,function(e){let{children:t}=e;return r.createElement(O.n2,null,r.createElement(L.M,null,r.createElement(D,null,t)))}]);function it(e){let{children:t}=e;return r.createElement(ot,null,t)}function lt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(u.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("p",null,t.message),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},r.createElement(u.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again when the page crashed"},"Try again"))))))}const st={mainWrapper:"mainWrapper_z2l0"};function ut(e){const{children:t,noFooter:n,wrapperClassName:l,title:s,description:u}=e;return(0,b.t)(),r.createElement(it,null,r.createElement(i.d,{title:s,description:u}),r.createElement(y,null),r.createElement(A,null),r.createElement($e,null),r.createElement("div",{id:d,className:(0,a.Z)(g.k.wrapper.main,st.mainWrapper,l)},r.createElement(o.Z,{fallback:e=>r.createElement(lt,e)},t)),!n&&r.createElement(at,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),l=n(2263),s=n(6668),u=n(941);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},l=a.createElement(u.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},l):l}function d(e){const{siteConfig:{title:t}}=(0,l.Z)(),{navbar:{title:n,logo:u}}=(0,s.L)(),{imageClassName:d,titleClassName:f,...p}=e,m=(0,i.Z)(u?.href||"/"),h=n?"":t,g=u?.alt??h;return a.createElement(o.Z,(0,r.Z)({to:m},p,u?.target&&{target:u.target}),u&&a.createElement(c,{logo:u,alt:g,imageClassName:d}),null!=n&&a.createElement("b",{className:f},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7462),a=n(7294),o=n(6010),i=n(2389),l=n(2949);const s={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function u(e){const t=(0,i.Z)(),{colorMode:n}=(0,l.I)(),{sources:u,className:c,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,p.map((e=>a.createElement("img",(0,r.Z)({key:e,src:u[e],alt:d,className:(0,o.Z)(s.themedImage,s[`themedImage--${e}`],c)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>l,z:()=>h});var r=n(7462),a=n(7294),o=n(412);const i="ease-in-out";function l(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const s={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function c(e,t){const n=t?s:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function d(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=r?.duration??function(e){const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??i}`,height:`${t}px`}}function l(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return c(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=s.height,e.style.overflow=s.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function f(e){if(!o.Z.canUseDOM)return e?s:u}function p(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:l,disableSSRStyle:s}=e;const u=(0,a.useRef)(null);return d({collapsibleRef:u,collapsed:n,animation:o}),a.createElement(t,{ref:u,style:s?void 0:f(n),onTransitionEnd:e=>{"height"===e.propertyName&&(c(u.current,n),i?.(n))},className:l},r)}function m(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[l,s]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&s(t)}),[o,t]),o?a.createElement(p,(0,r.Z)({},n,{collapsed:l})):null}function h(e){let{lazy:t,...n}=e;const r=t?m:p;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>p});var r=n(7294),a=n(2389),o=n(12),i=n(902),l=n(6668);const s=(0,o.WA)("docusaurus.announcement.dismiss"),u=(0,o.WA)("docusaurus.announcement.id"),c=()=>"true"===s.get(),d=e=>s.set(String(e)),f=r.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,l.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&c()));(0,r.useEffect)((()=>{o(c())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&d(!1),!r&&c()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(f.Provider,{value:n},t)}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>g,S:()=>h});var r=n(7294),a=n(412),o=n(902),i=n(12),l=n(6668);const s=r.createContext(void 0),u="theme",c=(0,i.WA)(u),d={light:"light",dark:"dark"},f=e=>e===d.dark?d.dark:d.light,p=e=>a.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{c.set(f(e))};function h(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,l.L)(),[a,o]=(0,r.useState)(p(e));(0,r.useEffect)((()=>{t&&c.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(o(t),a&&m(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?d.dark:d.light:e),c.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(a))}),[a]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=c.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const s=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||s.current?s.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:a,setColorMode:i,get isDarkTheme(){return a===d.dark},setLightTheme(){i(d.light)},setDarkTheme(){i(d.dark)}})),[a,i])}();return r.createElement(s.Provider,{value:n},t)}function g(){const e=(0,r.useContext)(s);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>g});var r=n(7294),a=n(4104),o=n(9935),i=n(6668),l=n(2802),s=n(902),u=n(12);const c=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,u.WA)(c(e),{persistence:t}).set(n)},read:(e,t)=>(0,u.WA)(c(e),{persistence:t}).get(),clear:(e,t)=>{(0,u.WA)(c(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const p=r.createContext(null);function m(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,l]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{l(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),l((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function h(e){let{children:t}=e;const n=m();return r.createElement(p.Provider,{value:n},t)}function g(e){let{children:t}=e;return l.cE?r.createElement(h,null,t):r.createElement(r.Fragment,null,t)}function b(){const e=(0,r.useContext)(p);if(!e)throw new s.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=b(),{preferredVersionName:l}=n[e];return{preferredVersion:t.versions.find((e=>e.name===l))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>s,b:()=>l});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function l(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function s(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t,version:n}=e;return r.createElement(o.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(o);if(null===e)throw new a.i6("DocsVersionProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var r=n(7294),a=n(3102),o=n(7524),i=n(6550),l=(n(1688),n(902));function s(e){!function(e){const t=(0,i.k6)(),n=(0,l.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var u=n(6668);const c=r.createContext(void 0);function d(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,u.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[i,l]=(0,r.useState)(!1);s((()=>{if(i)return l(!1),!1}));const c=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:c,shown:i})),[e,n,c,i])}function f(e){let{children:t}=e;const n=d();return r.createElement(c.Provider,{value:n},t)}function p(){const e=r.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>l,Zo:()=>s,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function s(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,l]=i,s=(0,a.Ql)(n);return(0,r.useEffect)((()=>{l({component:t,props:s})}),[l,t,s]),(0,r.useEffect)((()=>()=>l({component:null,props:null})),[l]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>u});var r=n(7294),a=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function l(){return a.Z.canUseDOM?window.innerWidth>i?o.desktop:o.mobile:o.ssr}const s=!1;function u(){const[e,t]=(0,r.useState)((()=>s?"ssr":l()));return(0,r.useEffect)((()=>{function e(){t(l())}const n=s?window.setTimeout(e,1e3):void 0;return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(n)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},2802:(e,t,n)=>{"use strict";n.d(t,{MN:()=>C,Wl:()=>m,_F:()=>v,cE:()=>f,jA:()=>h,xz:()=>p,hI:()=>x,lO:()=>k,vY:()=>S,oz:()=>E,s1:()=>w});var r=n(7294),a=n(6550),o=n(8790),i=n(4104),l=n(373),s=n(4477),u=n(1116);function c(e){return Array.from(new Set(e))}var d=n(8596);const f=!!i._r;function p(e){const t=(0,s.E)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function m(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=m(t);if(e)return e}}}function h(){const{pathname:e}=(0,a.TH)(),t=(0,u.V)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=y({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const g=(e,t)=>void 0!==e&&(0,d.Mg)(e,t),b=(e,t)=>e.some((e=>v(e,t)));function v(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||b(e.items,t))}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function w(){const e=(0,u.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function k(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,l.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>c([t,n,a].filter(Boolean))),[t,n,a])}function E(e,t){const n=k(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\n Available sidebar ids are:\n - ${Object.keys(t).join("\n- ")}`);return r[1]}),[e,n])}function S(e,t){const n=k(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`DocNavbarItem: couldn't find any doc with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${c(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function x(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,l=i.find((e=>(0,a.LX)(r.pathname,e)));if(!l)return null;const s=l.sidebar,u=s?n.docsSidebars[s]:void 0;return{docElement:(0,o.H)(i),sidebarName:s,sidebarItems:u}}function C(e){return e.filter((e=>"category"!==e.type||!!m(e)))}},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>c,VC:()=>p});var r=n(7294),a=n(6010),o=n(5742),i=n(226);function l(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var s=n(4996),u=n(2263);function c(e){let{title:t,description:n,keywords:a,image:i,children:l}=e;const c=function(e){const{siteConfig:t}=(0,u.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,s.C)(),f=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,c),t&&r.createElement("meta",{property:"og:title",content:c}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),f&&r.createElement("meta",{property:"og:image",content:f}),f&&r.createElement("meta",{name:"twitter:image",content:f}),l)}const d=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(d),l=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:l},r.createElement(o.Z,null,r.createElement("html",{className:l})),n)}function p(e){let{children:t}=e;const n=l(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(f,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>u,Ql:()=>s,i6:()=>l,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function s(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>l});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function l(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>s,RF:()=>d});var r=n(7294),a=n(412),o=n(2389),i=n(902);const l=r.createContext(void 0);function s(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(l.Provider,{value:n},t)}function u(){const e=(0,r.useContext)(l);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const c=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),a=(0,r.useRef)(c()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=c();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&at&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>r,os:()=>a});n(2263);const r="default";function a(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>s});n(7294),n(1688);const r="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,i||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),i=!0),null}var t}let i=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function s(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=o(t?.persistence);return null===n?l:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var r=n(2263),a=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,r.Z)(),{pathname:i}=(0,a.TH)(),l=o===n?e:e.replace(`/${o}/`,"/"),s=i.replace(e,"");return{createUrl:function(e){let{locale:r,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===n?`${l}`:`${l}${e}/`}(r)}${s}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="post-content";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}})},4184:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;ta});const a=function(){for(var e,t,n=0,a="";n{"use strict";n.d(t,{lX:()=>w,q_:()=>_,ob:()=>p,PP:()=>A,Ep:()=>f});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!u)for(;d--;d)i.unshift("..");!u||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var l=n(8776);function s(e){return"/"===e.charAt(0)?e:"/"+e}function u(e){return"/"===e.charAt(0)?e.substr(1):e}function c(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function p(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=p(e,t,h(),w.location);c.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function s(e){return r.isMemo(e)?i:l[e.$$typeof]||a}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var u=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=p(n);a&&a!==m&&e(t,a,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=s(t),h=s(n),g=0;g{"use strict";e.exports=function(e,t,n,r,a,o,i,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,a,o,i,l],c=0;(s=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),u=o.querySelector(r.barSelector),c=r.speed,d=r.easing;return o.offsetWidth,l((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,i(e,c,d)),1===e?(s(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){s(o,{transition:"all "+c+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),c)}),c)):setTimeout(t,c)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),l=e?"-100":o(n.status||0),u=document.querySelector(r.parent);return s(i,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&p(a),u!=document.body&&c(u,"nprogress-custom-parent"),u.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var l=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function u(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=f(e),r=n+t;u(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);u(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,a){for(var o,i,l=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),s=1;s{var r=n(5826);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return l(o(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=f;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,l="",c=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],f=n[1],p=n.index;if(l+=e.slice(i,p),i=p+d.length,f)l+=f[1];else{var m=e[i],h=n[2],g=n[3],b=n[4],v=n[5],y=n[6],w=n[7];l&&(r.push(l),l="");var k=null!=h&&null!=m&&m!==h,E="+"===y||"*"===y,S="?"===y||"*"===y,x=n[2]||c,C=b||v;r.push({name:g||o++,prefix:h||"",delimiter:x,optional:S,repeat:E,partial:k,asterisk:!!w,pattern:C?u(C):w?".*":"[^"+s(x)+"]+?"})}}return i{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);S+=E.value.length,E=E.next){var x=E.value;if(t.length>e.length)return;if(!(x instanceof a)){var C,_=1;if(v){if(!(C=o(k,S,e,b))||C.index>=e.length)break;var T=C.index,A=C.index+C[0].length,L=S;for(L+=E.value.length;T>=L;)L+=(E=E.next).value.length;if(S=L-=E.value.length,E.value instanceof a)continue;for(var R=E;R!==t.tail&&(Ld.reach&&(d.reach=D);var I=E.prev;if(O&&(I=s(t,I,O),S+=O.length),u(t,I,_),E=s(t,I,new a(f,g?r.tokenize(N,g):N,y,N)),P&&s(t,E,P),_>1){var M={cause:f+","+m,reach:D};i(e,t,n,E.prev,S,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function s(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function u(e,t,n){for(var r=t.next,a=0;a"+o.content+""},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(//g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",quot:'"'},s=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n0)){var l=f(/^\{$/,/^\}$/);if(-1===l)continue;for(var s=n;s=0&&p(u,"variable-input")}}}}function c(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function l(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function s(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function u(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,s(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function c(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,c={},d=s(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=l(i++,r)););return c[n]=a,n})).join(""),n,r),f=Object.keys(c);return i=0,function e(t){for(var n=0;n=f.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=f[i],o="string"==typeof r?r:r.content,l=o.indexOf(a);if(-1!==l){++i;var s=o.substring(0,l),d=u(c[a]),p=o.substring(l+a.length),m=[];if(s&&m.push(s),m.push(d),p){var h=[p];e(h),m.push.apply(m,h)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var g=r.content;Array.isArray(g)?e(g):e([g])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(//g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r*\.{3}(?:[^{}]|)*\})/.source;function o(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return r})).replace(//g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},l=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var s=i(a);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(s=i(t[r-1])+s,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",s,null,s)}a.content&&"string"!=typeof a.content&&l(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||l(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,l=i.length;-1!==n.code.indexOf(a=t(r,l));)++l;return i[l]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(l){for(var s=0;s=o.length);s++){var u=l[s];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=o[a],d=n.tokenStack[c],f="string"==typeof u?u:u.content,p=t(r,c),m=f.indexOf(p);if(m>-1){++a;var h=f.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=f.substring(m+p.length),v=[];h&&v.push.apply(v,i([h])),v.push(g),b&&v.push.apply(v,i([b])),"string"==typeof u?l.splice.apply(l,[s,1].concat(v)):u.content=v}}else u.content&&i(u.content)}return l}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (.comment can become .namespace--comment) or replace them with your defined ones (like .editor__comment). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the highlightAll and highlightAllUnder methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n "));var l={},s=e[r];if(s){function u(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in l))for(var i in a(t,o),l[t]=!0,n[t])l[i]=!0}t(s.require,u),t(s.optional,u),t(s.modify,u)}n[r]=l,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,l){var s=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),u=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(s);i=i.map(u),l=(l||[]).map(u);var c=n(i),d=n(l);i.forEach((function e(n){var r=s[n];t(r&&r.require,(function(t){t in d||(c[t]=!0,e(t))}))}));for(var f,p=r(s),m=c;a(m);){for(var h in f={},m){var g=s[h];t(g&&g.modify,(function(e){e in d&&(f[e]=!0)}))}for(var b in d)if(!(b in c))for(var v in p(b))if(v in c){f[b]=!0;break}for(var y in m=f)c[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,l={},s={};function u(e){if(e in l)return l[e];s[e]=!0;var a,c=[];for(var d in t(e))d in n&&c.push(d);if(0===c.length)a=r(e);else{var f=i(c.map((function(e){var t=u(e);return delete s[e],t})));o?a=o(f,(function(){return r(e)})):r(e)}return l[e]=a}for(var c in n)u(c);var d=[];for(var f in s)d.push(l[f]);return i(d)}(p,c,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n