diff --git a/404.html b/404.html index 7fea897..ad66d82 100644 --- a/404.html +++ b/404.html @@ -4,13 +4,13 @@ Page Not Found | Schulcloud-Verbund-Software Documentation - - + +
-
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.

- - +
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/images/Create_TLDRAW.drawio-b2b643ec2acbf8cb6647f12c8e42c817.svg b/assets/images/Create_TLDRAW.drawio-b2b643ec2acbf8cb6647f12c8e42c817.svg new file mode 100644 index 0000000..6ad4761 --- /dev/null +++ b/assets/images/Create_TLDRAW.drawio-b2b643ec2acbf8cb6647f12c8e42c817.svg @@ -0,0 +1,47 @@ + + + + diff --git a/assets/images/Delete_TLDRAW.drawio-f5069441506f0d87d2b28a6803400f4f.svg b/assets/images/Delete_TLDRAW.drawio-f5069441506f0d87d2b28a6803400f4f.svg new file mode 100644 index 0000000..5fa2c68 --- /dev/null +++ b/assets/images/Delete_TLDRAW.drawio-f5069441506f0d87d2b28a6803400f4f.svg @@ -0,0 +1,47 @@ + + + + diff --git a/assets/images/Use_TLDRAW.drawio-005bddb02f945fa9bd7acaef562e7538.svg b/assets/images/Use_TLDRAW.drawio-005bddb02f945fa9bd7acaef562e7538.svg new file mode 100644 index 0000000..519f195 --- /dev/null +++ b/assets/images/Use_TLDRAW.drawio-005bddb02f945fa9bd7acaef562e7538.svg @@ -0,0 +1,47 @@ + + + + diff --git a/assets/js/0579a3a5.209fe466.js b/assets/js/0579a3a5.209fe466.js new file mode 100644 index 0000000..f822e7a --- /dev/null +++ b/assets/js/0579a3a5.209fe466.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[5014],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>m});var r=a(7294);function l(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function n(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var s=r.createContext({}),d=function(e){var t=r.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},c=function(e){var t=d(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var a=e.components,l=e.mdxType,n=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=d(a),h=l,m=u["".concat(s,".").concat(h)]||u[h]||p[h]||n;return a?r.createElement(m,o(o({ref:t},c),{},{components:a})):r.createElement(m,o({ref:t},c))}));function m(e,t){var a=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var n=a.length,o=new Array(n);o[0]=h;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[u]="string"==typeof e?e:l,o[1]=i;for(var d=2;d{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>n,metadata:()=>i,toc:()=>d});var r=a(7462),l=(a(7294),a(3905));const n={},o="How it works",i={unversionedId:"tldraw-server/How it works",id:"tldraw-server/How it works",title:"How it works",description:"The terms Redis and Valkey are used here synonymously and should describe the used in-memory-database.",source:"@site/docs/tldraw-server/How it works.md",sourceDirName:"tldraw-server",slug:"/tldraw-server/How it works",permalink:"/docs/tldraw-server/How it works",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/tldraw-server/How it works.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"How it works",permalink:"/docs/syncronizations/TSP/How it works"},next:{title:"Local setup",permalink:"/docs/tldraw-server/Local setup"}},s={},d=[{value:"Configuration",id:"configuration",level:2},{value:"Create",id:"create",level:2},{value:"Usage",id:"usage",level:2},{value:"Connection",id:"connection",level:3},{value:"Sending updates/storing data",id:"sending-updatesstoring-data",level:3},{value:"Delete",id:"delete",level:2},{value:"Assets",id:"assets",level:2},{value:"files upload",id:"files-upload",level:3},{value:"files deletion",id:"files-deletion",level:3}],c={toc:d},u="wrapper";function p(e){let{components:t,...n}=e;return(0,l.kt)(u,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"how-it-works"},"How it works"),(0,l.kt)("p",null,"The terms Redis and Valkey are used here synonymously and should describe the used in-memory-database."),(0,l.kt)("h2",{id:"configuration"},"Configuration"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"AUTHORIZATION_API_HOST - host address of the authorization endpoint (schuldcloud-server)"),(0,l.kt)("li",{parentName:"ul"},"FEATURE_TLDRAW_ENABLED - flag determining if tldraw is enabled"),(0,l.kt)("li",{parentName:"ul"},"LOGGER_LOG_LEVEL - logging level"),(0,l.kt)("li",{parentName:"ul"},"LOGGER_EXIT_ON_ERROR - flag whether an error will cause the application to stop"),(0,l.kt)("li",{parentName:"ul"},"METRICS_COLLECT_DEFAULT - flag whether the default metrics shall be collected"),(0,l.kt)("li",{parentName:"ul"},"REDIS_CLUSTER_ENABLED - flag whether a redis cluster or used or not"),(0,l.kt)("li",{parentName:"ul"},"REDIS_URL - redis connection string"),(0,l.kt)("li",{parentName:"ul"},"REDIS_SENTINEL_SERVICE_NAME - name of the redis sentinel service"),(0,l.kt)("li",{parentName:"ul"},"REDIS_PREFIX - prefix to be used with redis database"),(0,l.kt)("li",{parentName:"ul"},"REDIS_SENTINEL_NAME - name of the redis sentinel"),(0,l.kt)("li",{parentName:"ul"},"REDIS_SENTINEL_PASSWORD - password for the redis sentinel"),(0,l.kt)("li",{parentName:"ul"},"S3_ACCESS_KEY - access key for S3 storage"),(0,l.kt)("li",{parentName:"ul"},"S3_BUCKET - name of the S3 bucket"),(0,l.kt)("li",{parentName:"ul"},"S3_ENDPOINT - URL of the S3 service"),(0,l.kt)("li",{parentName:"ul"},"S3_PORT - port number for the S3 service"),(0,l.kt)("li",{parentName:"ul"},"S3_SECRET_KEY - secret key for S3 storage"),(0,l.kt)("li",{parentName:"ul"},"S3_SSL - flag to enable or disable SSL for S3 storage"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_ASSETS_ENABLED - enables uploading assets to tldraw board"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_ASSETS_MAX_SIZE_BYTES - maximum asset size in bytes"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_ASSETS_ALLOWED_MIME_TYPES_LIST - list of allowed assets MIME types"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_WEBSOCKET_PATH - path for the tldraw websocket connection"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_WEBSOCKET_URL - URL for the tldraw websocket connection"),(0,l.kt)("li",{parentName:"ul"},"WORKER_MIN_MESSAGE_LIFETIME - minimal lifetime of a update message consumed by the worker"),(0,l.kt)("li",{parentName:"ul"},"WORKER_TASK_DEBOUNCE - minimum idle time (in milliseconds) of the pending task messages to be claimed"),(0,l.kt)("li",{parentName:"ul"},"WORKER_TRY_CLAIM_COUNT - the maximum number of task messages to claim"),(0,l.kt)("li",{parentName:"ul"},"X_API_ALLOWED_KEYS - list of allowed xAPI keys")),(0,l.kt)("p",null,"In order to have deletion functionality fully working locally you have to fill those feature flags, e.g.:"),(0,l.kt)("p",null,"tldraw-server :"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},'X_API_ALLOWED_KEYS="7ccd4e11-c6f6-48b0-81eb-abcdef123456"')),(0,l.kt)("p",null,"schulcloud-server :"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},'TLDRAW_ADMIN_API_CLIENT_API_KEY="7ccd4e11-c6f6-48b0-81eb-abcdef123456"'),(0,l.kt)("li",{parentName:"ul"},'TLDRAW_ADMIN_API_CLIENT_BASE_URL="http://localhost:3349"')),(0,l.kt)("h2",{id:"create"},"Create"),(0,l.kt)("p",null,(0,l.kt)("img",{alt:"Create tldraw workflow",src:a(6517).Z,width:"2344",height:"1940"})),(0,l.kt)("p",null,"The Tldraw board can be created by the user on the courses ColumnBoard. It has a representation in ColumnBoard as DrawingElement inside a card (BoardNode in db). After creating representation as DrawingElement we can enter actual Tldraw SPA client on click."),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"User enters ColumnBoard and creates Representation of whiteboard (tldraw) in Card."),(0,l.kt)("li",{parentName:"ol"},"Data is saved and feedback with proper creation is given - user can see Representation and can enter whiteboard."),(0,l.kt)("li",{parentName:"ol"},"By entering whiteboard user is redirected to SPA tldraw-client."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-client is starting WS connection with tldraw-server."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server first checks if user has permission to this resource (by checking if user has a permission to Representation of whiteboard - BoardNode).\nId of Representation is same as drawingName, which is visible in tldraw-client url."),(0,l.kt)("li",{parentName:"ol"},"If user has permission tldraw-server is allowing to remain connected and getting drawing data from S3 storage. If there is no drawing data available, the tldraw-server will create a new document automatically. ")),(0,l.kt)("h2",{id:"usage"},"Usage"),(0,l.kt)("p",null,(0,l.kt)("img",{alt:"Usage tldraw workflow",src:a(5316).Z,width:"4120",height:"2416"})),(0,l.kt)("h3",{id:"connection"},"Connection"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"User joins tldraw board."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-client connects to one of the tldraw-server pods and tries to establish websocket connection."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server calls schulcloud-server via HTTP requests to check user permissions. If everything is fine, the websocket connection is established."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server gets stored tldraw board data from S3 storage and sends it via websocket to connected user."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server starts subscribing to Redis PUBSUB channel corresponding to tldraw board name to listen to changes from other pods.")),(0,l.kt)("h3",{id:"sending-updatesstoring-data"},"Sending updates/storing data"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"Tldraw-client sends user's drawing changes to the tldraw-server via websocket connection."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server stores the board update in the valkey db - basically creates a diff between what's already stored and what's being updated."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server pushes the update to the boards Redis channel so that connected clients on different pods have synchronized board data."),(0,l.kt)("li",{parentName:"ol"},"Other pods subscribing to Redis channel send updates to their connected clients via websocket whenever they see a new message on Redis channel."),(0,l.kt)("li",{parentName:"ol"},"Finally the worker will run and persist the current state of the drawing data by applying all currently available updates from valkey on top of the stored drawing data and update the S3 storage accordingly.")),(0,l.kt)("h2",{id:"delete"},"Delete"),(0,l.kt)("p",null,(0,l.kt)("img",{alt:"Delete tldraw workflow",src:a(5598).Z,width:"2020",height:"1368"})),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"User from schulcloud app in ColumnBoard deletes whiteboard (tldraw) instance form Card."),(0,l.kt)("li",{parentName:"ol"},"Schulcloud-server is removing representation data in schulcloud-database - BoardNodes collection."),(0,l.kt)("li",{parentName:"ol"},"Schulcloud-server is calling tldraw-server to delete all data that has given id."),(0,l.kt)("li",{parentName:"ol"},"Tldraw-server sends a delete action via websocket to inform connected clients about deletion. Clients redirect away from Tldraw-board to ensure that no new messages are added to valkey database."),(0,l.kt)("li",{parentName:"ol"},"Finally the worker will run, clear all updates and data from the valkey db and delete the drawing data from the S3 storage.")),(0,l.kt)("h2",{id:"assets"},"Assets"),(0,l.kt)("h3",{id:"files-upload"},"files upload"),(0,l.kt)("p",null,"Images/GIFs can be uploaded into tldraw whiteboard by every user with access to the board. We use SVS FileStorageService to physically store uploaded assets while tldraw only holds URL to a resource."),(0,l.kt)("p",null,"The files are uploaded by calling schulcloud-api's fileController upload endpoint. This is possible because tldraw is represented as a boardnode called drawing-element. Mongo id of this drawing-element is a roomId used in URL param when connecting to a specific board."),(0,l.kt)("h3",{id:"files-deletion"},"files deletion"),(0,l.kt)("p",null,"The deletion of files is handled directly by the tldraw-client itself. On deletion in the UI, the client sends a delete request to the file storage. While awaiting the answer from file storage the editing of the Tldraw-board is blocked to prevent race conditions to the file storage."))}p.isMDXComponent=!0},6517:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/Create_TLDRAW.drawio-b2b643ec2acbf8cb6647f12c8e42c817.svg"},5598:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/Delete_TLDRAW.drawio-f5069441506f0d87d2b28a6803400f4f.svg"},5316:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/Use_TLDRAW.drawio-005bddb02f945fa9bd7acaef562e7538.svg"}}]); \ No newline at end of file diff --git a/assets/js/14307e05.5a8531b2.js b/assets/js/14307e05.5a8531b2.js deleted file mode 100644 index 200b731..0000000 --- a/assets/js/14307e05.5a8531b2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[2024],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>h});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var a=n.createContext({}),l=function(e){var t=n.useContext(a),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(a.Provider,{value:t},e.children)},p="mdxType",y={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),p=l(r),d=o,h=p["".concat(a,".").concat(d)]||p[d]||y[d]||c;return r?n.createElement(h,i(i({ref:t},u),{},{components:r})):n.createElement(h,i({ref:t},u))}));function h(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=r.length,i=new Array(c);i[0]=d;var s={};for(var a in t)hasOwnProperty.call(t,a)&&(s[a]=t[a]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var l=2;l{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>y,frontMatter:()=>c,metadata:()=>s,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const c={},i="Architecture",s={unversionedId:"syncronizations/TSP/Architecture",id:"syncronizations/TSP/Architecture",title:"Architecture",description:"TspSyncStrategy",source:"@site/docs/syncronizations/TSP/Architecture.md",sourceDirName:"syncronizations/TSP",slug:"/syncronizations/TSP/Architecture",permalink:"/docs/syncronizations/TSP/Architecture",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/syncronizations/TSP/Architecture.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Technical details",permalink:"/docs/services/tldraw/Technical details"},next:{title:"How it works",permalink:"/docs/syncronizations/TSP/How it works"}},a={},l=[{value:"TspSyncStrategy",id:"tspsyncstrategy",level:2}],u={toc:l},p="wrapper";function y(e){let{components:t,...c}=e;return(0,o.kt)(p,(0,n.Z)({},u,c,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"architecture"},"Architecture"),(0,o.kt)("h2",{id:"tspsyncstrategy"},"TspSyncStrategy"),(0,o.kt)("p",null,'This strategy handles the sync of schools, students, teachers and classes from TSP and replaces both the legacy TspBaseSyncer and TspSchoolSyncer. It responds to the target "tsp".'),(0,o.kt)("p",null,"The flow looks like this (some of the logic for syncing is done in the provisioning strategy which is shared with the login):"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Flow of the TSP sync strategy",src:r(9631).Z,width:"629",height:"1063"})))}y.isMDXComponent=!0},9631:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/tsp_sync_strategy-8b6e7d1d1d0d9bdcb0ad45012f279b99.png"}}]); \ No newline at end of file diff --git a/assets/js/14307e05.c00f4a4f.js b/assets/js/14307e05.c00f4a4f.js new file mode 100644 index 0000000..9d037d8 --- /dev/null +++ b/assets/js/14307e05.c00f4a4f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[2024],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>h});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var a=n.createContext({}),l=function(e){var t=n.useContext(a),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},p=function(e){var t=l(e.components);return n.createElement(a.Provider,{value:t},e.children)},u="mdxType",y={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,a=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=l(r),d=o,h=u["".concat(a,".").concat(d)]||u[d]||y[d]||c;return r?n.createElement(h,s(s({ref:t},p),{},{components:r})):n.createElement(h,s({ref:t},p))}));function h(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=r.length,s=new Array(c);s[0]=d;var i={};for(var a in t)hasOwnProperty.call(t,a)&&(i[a]=t[a]);i.originalType=e,i[u]="string"==typeof e?e:o,s[1]=i;for(var l=2;l{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>y,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const c={},s="Architecture",i={unversionedId:"syncronizations/TSP/Architecture",id:"syncronizations/TSP/Architecture",title:"Architecture",description:"TspSyncStrategy",source:"@site/docs/syncronizations/TSP/Architecture.md",sourceDirName:"syncronizations/TSP",slug:"/syncronizations/TSP/Architecture",permalink:"/docs/syncronizations/TSP/Architecture",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/syncronizations/TSP/Architecture.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Local Setup",permalink:"/docs/services/etherpad/Local setup"},next:{title:"How it works",permalink:"/docs/syncronizations/TSP/How it works"}},a={},l=[{value:"TspSyncStrategy",id:"tspsyncstrategy",level:2}],p={toc:l},u="wrapper";function y(e){let{components:t,...c}=e;return(0,o.kt)(u,(0,n.Z)({},p,c,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"architecture"},"Architecture"),(0,o.kt)("h2",{id:"tspsyncstrategy"},"TspSyncStrategy"),(0,o.kt)("p",null,'This strategy handles the sync of schools, students, teachers and classes from TSP and replaces both the legacy TspBaseSyncer and TspSchoolSyncer. It responds to the target "tsp".'),(0,o.kt)("p",null,"The flow looks like this (some of the logic for syncing is done in the provisioning strategy which is shared with the login):"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Flow of the TSP sync strategy",src:r(9631).Z,width:"629",height:"1063"})))}y.isMDXComponent=!0},9631:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/tsp_sync_strategy-8b6e7d1d1d0d9bdcb0ad45012f279b99.png"}}]); \ No newline at end of file diff --git a/assets/js/5bde3a12.7b8edd7b.js b/assets/js/5bde3a12.7b8edd7b.js deleted file mode 100644 index 4d43463..0000000 --- a/assets/js/5bde3a12.7b8edd7b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[4211],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),s=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=s(n),u=a,m=d["".concat(l,".").concat(u)]||d[u]||h[u]||o;return n?r.createElement(m,i(i({ref:t},c),{},{components:n})):r.createElement(m,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p[d]="string"==typeof e?e:a,i[1]=p;for(var s=2;s{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>p,toc:()=>s});var r=n(7462),a=(n(7294),n(3905));const o={},i="Local Setup",p={unversionedId:"services/etherpad/Local setup",id:"services/etherpad/Local setup",title:"Local Setup",description:"Running the Etherpad server",source:"@site/docs/services/etherpad/Local setup.md",sourceDirName:"services/etherpad",slug:"/services/etherpad/Local setup",permalink:"/docs/services/etherpad/Local setup",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/services/etherpad/Local setup.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"How it works",permalink:"/docs/services/etherpad/How it works"},next:{title:"How it works",permalink:"/docs/services/tldraw/How it works"}},l={},s=[{value:"Running the Etherpad server",id:"running-the-etherpad-server",level:2}],c={toc:s},d="wrapper";function h(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"local-setup"},"Local Setup"),(0,a.kt)("h2",{id:"running-the-etherpad-server"},"Running the Etherpad server"),(0,a.kt)("p",null,"To run the Etherpad service for the local development and resting purposes you can follow the below steps:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create a new dir that will contain all the needed files that we'll want to use when running the Etherpad service.\nCreate a directory called sc-etherpad\xa0and then enter it, in Unix-like systems you can use the following command: "),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"`mkdir sc-etherpad && cd sc-etherpad`\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create a new file called APIKEY.txt in it, with the following content:"),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd")),(0,a.kt)("p",{parentName:"li"},"We'll use this file to set a fixed Etherpad's API key on the Etherpad server's start.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create also a file called settings.env with the following content:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},'REQUIRE_SESSION="true"\nPAD_OPTIONS_SHOW_CHAT="true"\nDISABLE_IP_LOGGING="true"\nDEFAULT_PAD_TEXT="Schreib etwas!\\n\\nDieses Etherpad wird synchronisiert, w\xe4hrend du tippst, so dass alle Betrachter jederzeit den selben Text sehen. So k\xf6nnt ihr auf einfache Weise gemeinsam an Dokumenten arbeiten."\nDB_TYPE=mongodb\nDB_URL=mongodb://host.docker.internal:27017/etherpad\n')),(0,a.kt)("p",{parentName:"li"},"We'll use this file to provide all the needed environment variables to the Etherpad's server."),(0,a.kt)("p",{parentName:"li"},"Please note the last line, that contains the MongoDB connection string:"),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"DB_URL=mongodb://host.docker.internal:27017/etherpad")),(0,a.kt)("p",{parentName:"li"},"Here we're using the host.docker.internal hostname which should make it possible for the Etherpad's container to connect to the host's local network and should work out of the box e.g. on macOS. But please modify it accordingly to your needs and your Docker's network configuration. An alternative configuaration would be to use ",(0,a.kt)("inlineCode",{parentName:"p"},"DB_URL=mongodb://localhost:27017/etherpad")," and than add ",(0,a.kt)("inlineCode",{parentName:"p"},'--network="host"')," to the following docker run command.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Next, start the Etherpad's container:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"docker run -d \\\n -p 9001:9001 \\\n --env-file ./settings.env \\\n -v ./APIKEY.txt:/opt/etherpad-lite/APIKEY.txt \\\n --name sc-etherpad \\\n docker.io/etherpad/etherpad:2.0.0\n")),(0,a.kt)("p",{parentName:"li"},"Please note we're using the docker.io/etherpad/etherpad:2.0.0 image in the command above which might be not the one that is being used anytime in the future when you read this article. To make sure you're using the current version (the one that is currently being used in the SchulCloud platform), please refer to the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/hpi-schul-cloud/dof_app_deploy/blob/main/ansible/group_vars/infra/dof_etherpad.yml"},"https://github.com/hpi-schul-cloud/dof_app_deploy/blob/main/ansible/group_vars/infra/dof_etherpad.yml")," file."))),(0,a.kt)("p",null,"Now we should have the Etherpad service running locally on port 9001, we can verify it's working properly e.g. by fetching the current Etherpad's API version:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 200 OK\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 26\n< ETag: W/"1a-2HmNLqF3wPt+KQRlEmGwH4O+xu4"\n< Date: Fri, 29 Mar 2024 13:27:00 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"currentVersion":"1.3.0"}\n')),(0,a.kt)("p",null,"We can also verify that the API key has been set successfully, let's use the example API call from the Etherpad's documentation ( ",(0,a.kt)("a",{parentName:"p",href:"https://etherpad.org/doc/v2.0.0/#_example_1"},"https://etherpad.org/doc/v2.0.0/#_example_1")," ):"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api/1/createAuthorIfNotExistsFor\\?apikey\\=381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd\\&name\\=Michael\\&authorMapper\\=7\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api/1/createAuthorIfNotExistsFor?apikey=381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd&name=Michael&authorMapper=7 HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 200 OK\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 66\n< ETag: W/"42-bg92QA1xRFO6QmkNRbNXhfsFBUM"\n< Date: Fri, 29 Mar 2024 13:40:05 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"code":0,"message":"ok","data":{"authorID":"a.7BgkAuzbHXR1G8Cv"}}\n')),(0,a.kt)("p",null,"In case of an unsuccessful result (e.g. improperly set or invalid API key) we would receive the following response:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api/1/createAuthorIfNotExistsFor\\?apikey\\=secret\\&name\\=Michael\\&authorMapper\\=7\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7 HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 401 Unauthorized\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 54\n< ETag: W/"36-dbJd0O+vdNi3zPpwRXE+1EGLTho"\n< Date: Fri, 29 Mar 2024 13:39:44 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"code":4,"message":"no or wrong API Key","data":null}\n')))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5bde3a12.bbb6e7d2.js b/assets/js/5bde3a12.bbb6e7d2.js new file mode 100644 index 0000000..7722c68 --- /dev/null +++ b/assets/js/5bde3a12.bbb6e7d2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[4211],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),s=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=s(n),u=a,m=d["".concat(l,".").concat(u)]||d[u]||h[u]||o;return n?r.createElement(m,i(i({ref:t},c),{},{components:n})):r.createElement(m,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p[d]="string"==typeof e?e:a,i[1]=p;for(var s=2;s{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>p,toc:()=>s});var r=n(7462),a=(n(7294),n(3905));const o={},i="Local Setup",p={unversionedId:"services/etherpad/Local setup",id:"services/etherpad/Local setup",title:"Local Setup",description:"Running the Etherpad server",source:"@site/docs/services/etherpad/Local setup.md",sourceDirName:"services/etherpad",slug:"/services/etherpad/Local setup",permalink:"/docs/services/etherpad/Local setup",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/services/etherpad/Local setup.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"How it works",permalink:"/docs/services/etherpad/How it works"},next:{title:"Architecture",permalink:"/docs/syncronizations/TSP/Architecture"}},l={},s=[{value:"Running the Etherpad server",id:"running-the-etherpad-server",level:2}],c={toc:s},d="wrapper";function h(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"local-setup"},"Local Setup"),(0,a.kt)("h2",{id:"running-the-etherpad-server"},"Running the Etherpad server"),(0,a.kt)("p",null,"To run the Etherpad service for the local development and resting purposes you can follow the below steps:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create a new dir that will contain all the needed files that we'll want to use when running the Etherpad service.\nCreate a directory called sc-etherpad\xa0and then enter it, in Unix-like systems you can use the following command: "),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"`mkdir sc-etherpad && cd sc-etherpad`\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create a new file called APIKEY.txt in it, with the following content:"),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd")),(0,a.kt)("p",{parentName:"li"},"We'll use this file to set a fixed Etherpad's API key on the Etherpad server's start.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Create also a file called settings.env with the following content:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},'REQUIRE_SESSION="true"\nPAD_OPTIONS_SHOW_CHAT="true"\nDISABLE_IP_LOGGING="true"\nDEFAULT_PAD_TEXT="Schreib etwas!\\n\\nDieses Etherpad wird synchronisiert, w\xe4hrend du tippst, so dass alle Betrachter jederzeit den selben Text sehen. So k\xf6nnt ihr auf einfache Weise gemeinsam an Dokumenten arbeiten."\nDB_TYPE=mongodb\nDB_URL=mongodb://host.docker.internal:27017/etherpad\n')),(0,a.kt)("p",{parentName:"li"},"We'll use this file to provide all the needed environment variables to the Etherpad's server."),(0,a.kt)("p",{parentName:"li"},"Please note the last line, that contains the MongoDB connection string:"),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"DB_URL=mongodb://host.docker.internal:27017/etherpad")),(0,a.kt)("p",{parentName:"li"},"Here we're using the host.docker.internal hostname which should make it possible for the Etherpad's container to connect to the host's local network and should work out of the box e.g. on macOS. But please modify it accordingly to your needs and your Docker's network configuration. An alternative configuaration would be to use ",(0,a.kt)("inlineCode",{parentName:"p"},"DB_URL=mongodb://localhost:27017/etherpad")," and than add ",(0,a.kt)("inlineCode",{parentName:"p"},'--network="host"')," to the following docker run command.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Next, start the Etherpad's container:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"docker run -d \\\n -p 9001:9001 \\\n --env-file ./settings.env \\\n -v ./APIKEY.txt:/opt/etherpad-lite/APIKEY.txt \\\n --name sc-etherpad \\\n docker.io/etherpad/etherpad:2.0.0\n")),(0,a.kt)("p",{parentName:"li"},"Please note we're using the docker.io/etherpad/etherpad:2.0.0 image in the command above which might be not the one that is being used anytime in the future when you read this article. To make sure you're using the current version (the one that is currently being used in the SchulCloud platform), please refer to the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/hpi-schul-cloud/dof_app_deploy/blob/main/ansible/group_vars/infra/dof_etherpad.yml"},"https://github.com/hpi-schul-cloud/dof_app_deploy/blob/main/ansible/group_vars/infra/dof_etherpad.yml")," file."))),(0,a.kt)("p",null,"Now we should have the Etherpad service running locally on port 9001, we can verify it's working properly e.g. by fetching the current Etherpad's API version:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 200 OK\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 26\n< ETag: W/"1a-2HmNLqF3wPt+KQRlEmGwH4O+xu4"\n< Date: Fri, 29 Mar 2024 13:27:00 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"currentVersion":"1.3.0"}\n')),(0,a.kt)("p",null,"We can also verify that the API key has been set successfully, let's use the example API call from the Etherpad's documentation ( ",(0,a.kt)("a",{parentName:"p",href:"https://etherpad.org/doc/v2.0.0/#_example_1"},"https://etherpad.org/doc/v2.0.0/#_example_1")," ):"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api/1/createAuthorIfNotExistsFor\\?apikey\\=381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd\\&name\\=Michael\\&authorMapper\\=7\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api/1/createAuthorIfNotExistsFor?apikey=381d67e6347d235ac9446da3ea10a82efd6f8ae09fa2e90efeda80f82feeb4fd&name=Michael&authorMapper=7 HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 200 OK\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 66\n< ETag: W/"42-bg92QA1xRFO6QmkNRbNXhfsFBUM"\n< Date: Fri, 29 Mar 2024 13:40:05 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"code":0,"message":"ok","data":{"authorID":"a.7BgkAuzbHXR1G8Cv"}}\n')),(0,a.kt)("p",null,"In case of an unsuccessful result (e.g. improperly set or invalid API key) we would receive the following response:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'~ curl -v http://127.0.0.1:9001/api/1/createAuthorIfNotExistsFor\\?apikey\\=secret\\&name\\=Michael\\&authorMapper\\=7\n* Trying 127.0.0.1:9001...\n* Connected to 127.0.0.1 (127.0.0.1) port 9001\n> GET /api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7 HTTP/1.1\n> Host: 127.0.0.1:9001\n> User-Agent: curl/8.4.0\n> Accept: */*\n> \n< HTTP/1.1 401 Unauthorized\n< X-Powered-By: Express\n< X-UA-Compatible: IE=Edge,chrome=1\n< Referrer-Policy: same-origin\n< Content-Type: application/json; charset=utf-8\n< Content-Length: 54\n< ETag: W/"36-dbJd0O+vdNi3zPpwRXE+1EGLTho"\n< Date: Fri, 29 Mar 2024 13:39:44 GMT\n< Connection: keep-alive\n< Keep-Alive: timeout=5\n< \n* Connection #0 to host 127.0.0.1 left intact\n{"code":4,"message":"no or wrong API Key","data":null}\n')))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/74c4112b.b7c648c5.js b/assets/js/74c4112b.b7c648c5.js new file mode 100644 index 0000000..6d08745 --- /dev/null +++ b/assets/js/74c4112b.b7c648c5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[6190],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>w});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var s=a.createContext({}),c=function(e){var t=a.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,o=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=c(r),m=n,w=p["".concat(s,".").concat(m)]||p[m]||d[m]||o;return r?a.createElement(w,l(l({ref:t},u),{},{components:r})):a.createElement(w,l({ref:t},u))}));function w(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=r.length,l=new Array(o);l[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[p]="string"==typeof e?e:n,l[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var a=r(7462),n=(r(7294),r(3905));const o={},l="Local setup",i={unversionedId:"tldraw-server/Local setup",id:"tldraw-server/Local setup",title:"Local setup",description:"To run tldraw locally:",source:"@site/docs/tldraw-server/Local setup.md",sourceDirName:"tldraw-server",slug:"/tldraw-server/Local setup",permalink:"/docs/tldraw-server/Local setup",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/tldraw-server/Local setup.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"How it works",permalink:"/docs/tldraw-server/How it works"},next:{title:"Technical details",permalink:"/docs/tldraw-server/Technical details"}},s={},c=[{value:"To run tldraw locally:",id:"to-run-tldraw-locally",level:3},{value:"Create new whiteboard:",id:"create-new-whiteboard",level:3}],u={toc:c},p="wrapper";function d(e){let{components:t,...r}=e;return(0,n.kt)(p,(0,a.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"local-setup"},"Local setup"),(0,n.kt)("h3",{id:"to-run-tldraw-locally"},"To run tldraw locally:"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"Run redis i.e. in a docker container, it will work on localhost:6379 by default which is what the REDIS_URI env var is set to, for example on wsl: ",(0,n.kt)("a",{parentName:"li",href:"https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/"},"https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/")," ."),(0,n.kt)("li",{parentName:"ol"},"In the tldraw-server make a copy of .env.default and rename it to .env, in order to use the default configuration."),(0,n.kt)("li",{parentName:"ol"},"To run",(0,n.kt)("ol",{parentName:"li"},(0,n.kt)("li",{parentName:"ol"},"npm run nest:start:dev (schulcloud-server)"),(0,n.kt)("li",{parentName:"ol"},"npm run nest:start:files-storage:dev (schulcloud-server with s3, if you want to upload files)"),(0,n.kt)("li",{parentName:"ol"},"npm run start:server:dev (tldraw-server)"),(0,n.kt)("li",{parentName:"ol"},"npm run start:worker:dev (tldraw-server)"),(0,n.kt)("li",{parentName:"ol"},"npm run dev (schulcloud-client)"),(0,n.kt)("li",{parentName:"ol"},"npm run servce (nuxt-client)"),(0,n.kt)("li",{parentName:"ol"},"npm run dev (tldraw-client)")))),(0,n.kt)("h3",{id:"create-new-whiteboard"},"Create new whiteboard:"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"Go to a course."),(0,n.kt)("li",{parentName:"ol"},"Go to 'Column board'."),(0,n.kt)("li",{parentName:"ol"},"Create a new card and a new 'Whiteboard' element within it, then click it."),(0,n.kt)("li",{parentName:"ol"},"A new browser tab with URL like: http://localhost:4000/tldraw?roomName=65c37329b2f97cc714d31c00 will open."),(0,n.kt)("li",{parentName:"ol"},"Change the port part from 4000 to 3046, which is the default port of tldraw-client app."),(0,n.kt)("li",{parentName:"ol"},"You should see a working tldraw whiteboard now.")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.2ed88293.js b/assets/js/935f2afb.2ed88293.js new file mode 100644 index 0000000..77fa7fc --- /dev/null +++ b/assets/js/935f2afb.2ed88293.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).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":{"tutorialSidebar":[{"type":"link","label":"Schulcloud Documentation","href":"/docs/intro","docId":"intro"},{"type":"category","label":"nuxt-client","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting Started","href":"/docs/nuxt-client/GettingStarted","docId":"nuxt-client/GettingStarted"},{"type":"link","label":"Project Structure","href":"/docs/nuxt-client/ProjectStructure","docId":"nuxt-client/ProjectStructure"},{"type":"link","label":"Code Conventions","href":"/docs/nuxt-client/CodeConventions","docId":"nuxt-client/CodeConventions"},{"type":"link","label":"Git Conventions","href":"/docs/nuxt-client/GitConventions","docId":"nuxt-client/GitConventions"},{"type":"link","label":"How To","href":"/docs/nuxt-client/HowTo","docId":"nuxt-client/HowTo"},{"type":"link","label":"Writing Tests","href":"/docs/nuxt-client/WritingTests","docId":"nuxt-client/WritingTests"},{"type":"link","label":"Accessibility (A11y)","href":"/docs/nuxt-client/Accessibility","docId":"nuxt-client/Accessibility"},{"type":"link","label":"Colors","href":"/docs/nuxt-client/Colors","docId":"nuxt-client/Colors"},{"type":"link","label":"Identifying and Resolving Circular Dependencies","href":"/docs/nuxt-client/IdentifyingAndResolvingCircularDependencies","docId":"nuxt-client/IdentifyingAndResolvingCircularDependencies"},{"type":"link","label":"Hints for Working","href":"/docs/nuxt-client/HintsForWorking","docId":"nuxt-client/HintsForWorking"},{"type":"link","label":"Component Development Guidelines","href":"/docs/nuxt-client/ComponentGuidelines","docId":"nuxt-client/ComponentGuidelines"}],"href":"/docs/category/nuxt-client"},{"type":"category","label":"schulcloud-client","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting started","href":"/docs/schulcloud-client/Getting started","docId":"schulcloud-client/Getting started"}],"href":"/docs/category/schulcloud-client"},{"type":"category","label":"schulcloud-server","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting started","href":"/docs/schulcloud-server/Getting started","docId":"schulcloud-server/Getting started"},{"type":"link","label":"API design","href":"/docs/schulcloud-server/Api","docId":"schulcloud-server/Api"},{"type":"category","label":"Coding-Guidelines","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Access legacy Code","href":"/docs/schulcloud-server/Coding-Guidelines/access-legacy-code","docId":"schulcloud-server/Coding-Guidelines/access-legacy-code"},{"type":"link","label":"Code Style","href":"/docs/schulcloud-server/Coding-Guidelines/code-style","docId":"schulcloud-server/Coding-Guidelines/code-style"},{"type":"link","label":"Configuration","href":"/docs/schulcloud-server/Coding-Guidelines/configuration","docId":"schulcloud-server/Coding-Guidelines/configuration"},{"type":"link","label":"Controller","href":"/docs/schulcloud-server/Coding-Guidelines/controllers","docId":"schulcloud-server/Coding-Guidelines/controllers"},{"type":"link","label":"Deprecation Workflow","href":"/docs/schulcloud-server/Coding-Guidelines/deprection-workflow","docId":"schulcloud-server/Coding-Guidelines/deprection-workflow"},{"type":"link","label":"Domain Object Validation","href":"/docs/schulcloud-server/Coding-Guidelines/domain-object-validation","docId":"schulcloud-server/Coding-Guidelines/domain-object-validation"},{"type":"link","label":"Event Handling","href":"/docs/schulcloud-server/Coding-Guidelines/event-handling","docId":"schulcloud-server/Coding-Guidelines/event-handling"},{"type":"link","label":"Exception Handling","href":"/docs/schulcloud-server/Coding-Guidelines/exception-handling","docId":"schulcloud-server/Coding-Guidelines/exception-handling"},{"type":"link","label":"Logging","href":"/docs/schulcloud-server/Coding-Guidelines/logging","docId":"schulcloud-server/Coding-Guidelines/logging"},{"type":"link","label":"Defining Entities","href":"/docs/schulcloud-server/Coding-Guidelines/micro-orm","docId":"schulcloud-server/Coding-Guidelines/micro-orm"},{"type":"link","label":"Implementation and usage of modules, submodule and barrel files in our project","href":"/docs/schulcloud-server/Coding-Guidelines/modules-submodules","docId":"schulcloud-server/Coding-Guidelines/modules-submodules"},{"type":"link","label":"Repositories","href":"/docs/schulcloud-server/Coding-Guidelines/repositories","docId":"schulcloud-server/Coding-Guidelines/repositories"},{"type":"link","label":"Testing","href":"/docs/schulcloud-server/Coding-Guidelines/testing","docId":"schulcloud-server/Coding-Guidelines/testing"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Git","href":"/docs/schulcloud-server/Development/git","docId":"schulcloud-server/Development/git"},{"type":"link","label":"ErWIn-IDM (Keycloak)","href":"/docs/schulcloud-server/Development/keycloak","docId":"schulcloud-server/Development/keycloak"},{"type":"link","label":"Rocket.Chat","href":"/docs/schulcloud-server/Development/rocket-chat","docId":"schulcloud-server/Development/rocket-chat"},{"type":"link","label":"VSCode","href":"/docs/schulcloud-server/Development/vs-code","docId":"schulcloud-server/Development/vs-code"}]},{"type":"link","label":"Migrations","href":"/docs/schulcloud-server/Migrations","docId":"schulcloud-server/Migrations"},{"type":"link","label":"Software Architecture","href":"/docs/schulcloud-server/architecture","docId":"schulcloud-server/architecture"},{"type":"category","label":"our nextjs modules","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Room Member Module","href":"/docs/schulcloud-server/our nextjs modules/room-member-module/","docId":"schulcloud-server/our nextjs modules/room-member-module/index"}]}],"href":"/docs/category/schulcloud-server"},{"type":"category","label":"e2e-system-tests","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting Started","href":"/docs/e2e-system-tests/GettingStarted","docId":"e2e-system-tests/GettingStarted"},{"type":"link","label":"Project Structure","href":"/docs/e2e-system-tests/ProjectStructure","docId":"e2e-system-tests/ProjectStructure"},{"type":"link","label":"Code Conventions","href":"/docs/e2e-system-tests/CodeConventions","docId":"e2e-system-tests/CodeConventions"},{"type":"link","label":"Tags","href":"/docs/e2e-system-tests/Tags","docId":"e2e-system-tests/Tags"}],"href":"/docs/category/e2e-system-tests"},{"type":"category","label":"How to update the docs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Create a Page","href":"/docs/How to update the docs/create-a-page","docId":"How to update the docs/create-a-page"},{"type":"link","label":"Create a Document","href":"/docs/How to update the docs/create-a-document","docId":"How to update the docs/create-a-document"},{"type":"link","label":"Create a Blog Post","href":"/docs/How to update the docs/create-a-blog-post","docId":"How to update the docs/create-a-blog-post"},{"type":"link","label":"Markdown Features","href":"/docs/How to update the docs/markdown-features","docId":"How to update the docs/markdown-features"},{"type":"link","label":"Deploy your site","href":"/docs/How to update the docs/deploy-your-site","docId":"How to update the docs/deploy-your-site"},{"type":"link","label":"Congratulations!","href":"/docs/How to update the docs/congratulations","docId":"How to update the docs/congratulations"}],"href":"/docs/category/how-to-update-the-docs"},{"type":"category","label":"Informations","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Detect Dependency Cycles","href":"/docs/Informations/detect-dependency-cycles","docId":"Informations/detect-dependency-cycles"}]},{"type":"category","label":"services","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"etherpad","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How it works","href":"/docs/services/etherpad/How it works","docId":"services/etherpad/How it works"},{"type":"link","label":"Local Setup","href":"/docs/services/etherpad/Local setup","docId":"services/etherpad/Local setup"}]}]},{"type":"category","label":"syncronizations","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"TSP","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Architecture","href":"/docs/syncronizations/TSP/Architecture","docId":"syncronizations/TSP/Architecture"},{"type":"link","label":"How it works","href":"/docs/syncronizations/TSP/How it works","docId":"syncronizations/TSP/How it works"}]}]},{"type":"category","label":"tldraw-server","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How it works","href":"/docs/tldraw-server/How it works","docId":"tldraw-server/How it works"},{"type":"link","label":"Local setup","href":"/docs/tldraw-server/Local setup","docId":"tldraw-server/Local setup"},{"type":"link","label":"Technical details","href":"/docs/tldraw-server/Technical details","docId":"tldraw-server/Technical details"}]}]},"docs":{"e2e-system-tests/CodeConventions":{"id":"e2e-system-tests/CodeConventions","title":"Code Conventions","description":"This guide provides coding conventions and best practices for writing feature files, naming folders, files, methods, and step definitions. Following these conventions will ensure consistency and maintainability across the test framework.","sidebar":"tutorialSidebar"},"e2e-system-tests/GettingStarted":{"id":"e2e-system-tests/GettingStarted","title":"Getting Started","description":"This section provides instructions for setting up the Cypress-Cucumber test environment to ensure a smooth onboarding process.","sidebar":"tutorialSidebar"},"e2e-system-tests/ProjectStructure":{"id":"e2e-system-tests/ProjectStructure","title":"Project Structure","description":"Understanding the project directory layout will help you navigate and manage the Cypress-Cucumber E2E test framework effectively. This section provides a detailed breakdown of the folder structure and the purpose of each component.","sidebar":"tutorialSidebar"},"e2e-system-tests/Tags":{"id":"e2e-system-tests/Tags","title":"Tags","description":"This section explains the tagging system used for Cypress and Cucumber tests. Tags help categorize and selectively run tests based on environments, test stability, or purpose.","sidebar":"tutorialSidebar"},"How to update the docs/congratulations":{"id":"How to update the docs/congratulations","title":"Congratulations!","description":"You have just learned the basics of Docusaurus and made some changes to the initial template.","sidebar":"tutorialSidebar"},"How to update the docs/create-a-blog-post":{"id":"How to update the docs/create-a-blog-post","title":"Create a Blog Post","description":"Docusaurus creates a page for each blog post, but also a blog index page, a tag system, an RSS feed...","sidebar":"tutorialSidebar"},"How to update the docs/create-a-document":{"id":"How to update the docs/create-a-document","title":"Create a Document","description":"Documents are groups of pages connected through:","sidebar":"tutorialSidebar"},"How to update the docs/create-a-page":{"id":"How to update the docs/create-a-page","title":"Create a Page","description":"Add Markdown or React files to src/pages to create a standalone page:","sidebar":"tutorialSidebar"},"How to update the docs/deploy-your-site":{"id":"How to update the docs/deploy-your-site","title":"Deploy your site","description":"Docusaurus is a static-site-generator (also called Jamstack).","sidebar":"tutorialSidebar"},"How to update the docs/markdown-features":{"id":"How to update the docs/markdown-features","title":"Markdown Features","description":"Docusaurus supports Markdown and a few additional features.","sidebar":"tutorialSidebar"},"Informations/detect-dependency-cycles":{"id":"Informations/detect-dependency-cycles","title":"Detect Dependency Cycles","description":"You can use following package and command to detect dependency cycles in code.","sidebar":"tutorialSidebar"},"intro":{"id":"intro","title":"Schulcloud Documentation","description":"The schulcloud consists of many repositories.","sidebar":"tutorialSidebar"},"nuxt-client/Accessibility":{"id":"nuxt-client/Accessibility","title":"Accessibility (A11y)","description":"We want to make sure that our product can be used by anyone.","sidebar":"tutorialSidebar"},"nuxt-client/CodeConventions":{"id":"nuxt-client/CodeConventions","title":"Code Conventions","description":"- Code Conventions","sidebar":"tutorialSidebar"},"nuxt-client/Colors":{"id":"nuxt-client/Colors","title":"Colors","description":"In the Material Design system (the foundation of our component library), colors and color schemes are used to create a visual hierarchy, direct focus, and enhance the user experience.","sidebar":"tutorialSidebar"},"nuxt-client/ComponentGuidelines":{"id":"nuxt-client/ComponentGuidelines","title":"Component Development Guidelines","description":"HTML is not a string","sidebar":"tutorialSidebar"},"nuxt-client/GettingStarted":{"id":"nuxt-client/GettingStarted","title":"Getting Started","description":"Development Setup","sidebar":"tutorialSidebar"},"nuxt-client/GitConventions":{"id":"nuxt-client/GitConventions","title":"Git Conventions","description":"Each change should be done in a Ticket (no matter how small).","sidebar":"tutorialSidebar"},"nuxt-client/HintsForWorking":{"id":"nuxt-client/HintsForWorking","title":"Hints for Working","description":"Working with Material Design Icons","sidebar":"tutorialSidebar"},"nuxt-client/HowTo":{"id":"nuxt-client/HowTo","title":"How To","description":"Collection of instructions on how to do certain things:","sidebar":"tutorialSidebar"},"nuxt-client/IdentifyingAndResolvingCircularDependencies":{"id":"nuxt-client/IdentifyingAndResolvingCircularDependencies","title":"Identifying and Resolving Circular Dependencies","description":"What is a circular dependency?","sidebar":"tutorialSidebar"},"nuxt-client/ProjectStructure":{"id":"nuxt-client/ProjectStructure","title":"Project Structure","description":"Filenames","sidebar":"tutorialSidebar"},"nuxt-client/WritingTests":{"id":"nuxt-client/WritingTests","title":"Writing Tests","description":"How to write valuable, reliable tests, that are easy to maintain.","sidebar":"tutorialSidebar"},"schulcloud-client/Getting started":{"id":"schulcloud-client/Getting started","title":"Getting started","description":"Make sure to have the following software installed","sidebar":"tutorialSidebar"},"schulcloud-server/Api":{"id":"schulcloud-server/Api","title":"API design","description":"nest.js","sidebar":"tutorialSidebar"},"schulcloud-server/architecture":{"id":"schulcloud-server/architecture","title":"Software Architecture","description":"Goals","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/access-legacy-code":{"id":"schulcloud-server/Coding-Guidelines/access-legacy-code","title":"Access legacy Code","description":"Access Feathers Service from NestJS","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/code-style":{"id":"schulcloud-server/Coding-Guidelines/code-style","title":"Code Style","description":"Function","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/configuration":{"id":"schulcloud-server/Coding-Guidelines/configuration","title":"Configuration","description":"The Configuration Management consists of three layers working together.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/controllers":{"id":"schulcloud-server/Coding-Guidelines/controllers","title":"Controller","description":"A modules api layer is defined within of controllers.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/deprection-workflow":{"id":"schulcloud-server/Coding-Guidelines/deprection-workflow","title":"Deprecation Workflow","description":"When to use 2 step migration","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/domain-object-validation":{"id":"schulcloud-server/Coding-Guidelines/domain-object-validation","title":"Domain Object Validation","description":"If you need to validate a domain object, please write an independent class, so that the domain object itself, its repo and services can reuse it.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/event-handling":{"id":"schulcloud-server/Coding-Guidelines/event-handling","title":"Event Handling","description":"Internal Events are used as a mechanism for Dependency Inversion.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/exception-handling":{"id":"schulcloud-server/Coding-Guidelines/exception-handling","title":"Exception Handling","description":"exception hierarchy","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/logging":{"id":"schulcloud-server/Coding-Guidelines/logging","title":"Logging","description":"For logging use the Logger, exported by the logger module. It encapsulates a Winston logger. Its injection scope is transient, so you can set a context when you inject it.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/micro-orm":{"id":"schulcloud-server/Coding-Guidelines/micro-orm","title":"Defining Entities","description":"When defining entities with MikroORM (Version 5), the following should be considered:","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/modules-submodules":{"id":"schulcloud-server/Coding-Guidelines/modules-submodules","title":"Implementation and usage of modules, submodule and barrel files in our project","description":"In this guide, we\'ll cover how to use modules, submodules and barrel files in our project. These concepts help you organize your code into separate files and directories, making it easier to manage and maintain.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/repositories":{"id":"schulcloud-server/Coding-Guidelines/repositories","title":"Repositories","description":"The repository is responsible to provide domain objects for the domain layer. Typically, it does so by accessing a database.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/testing":{"id":"schulcloud-server/Coding-Guidelines/testing","title":"Testing","description":"Automated testing is the essential part of the software development process.","sidebar":"tutorialSidebar"},"schulcloud-server/Development/git":{"id":"schulcloud-server/Development/git","title":"Git","description":"Branch name conventions","sidebar":"tutorialSidebar"},"schulcloud-server/Development/keycloak":{"id":"schulcloud-server/Development/keycloak","title":"ErWIn-IDM (Keycloak)","description":"ErWIn-IDM, namely Keycloak, will be the future Identity Management System (IDM) for the dBildungscloud. Keycloak","sidebar":"tutorialSidebar"},"schulcloud-server/Development/rocket-chat":{"id":"schulcloud-server/Development/rocket-chat","title":"Rocket.Chat","description":"Start Mongodb","sidebar":"tutorialSidebar"},"schulcloud-server/Development/vs-code":{"id":"schulcloud-server/Development/vs-code","title":"VSCode","description":"Launch scripts","sidebar":"tutorialSidebar"},"schulcloud-server/Getting started":{"id":"schulcloud-server/Getting started","title":"Getting started","description":"Make sure to have the following software installed","sidebar":"tutorialSidebar"},"schulcloud-server/Migrations":{"id":"schulcloud-server/Migrations","title":"Migrations","description":"Migrations for server database","sidebar":"tutorialSidebar"},"schulcloud-server/our nextjs modules/room-member-module/index":{"id":"schulcloud-server/our nextjs modules/room-member-module/index","title":"Room Member Module","description":"The Room Member module manages the association between users and rooms, handling permissions and roles within rooms. This module is designed to be injected into the Room module for managing user access and roles within rooms.","sidebar":"tutorialSidebar"},"services/etherpad/How it works":{"id":"services/etherpad/How it works","title":"How it works","description":"Configuration","sidebar":"tutorialSidebar"},"services/etherpad/Local setup":{"id":"services/etherpad/Local setup","title":"Local Setup","description":"Running the Etherpad server","sidebar":"tutorialSidebar"},"syncronizations/TSP/Architecture":{"id":"syncronizations/TSP/Architecture","title":"Architecture","description":"TspSyncStrategy","sidebar":"tutorialSidebar"},"syncronizations/TSP/How it works":{"id":"syncronizations/TSP/How it works","title":"How it works","description":"Configuration","sidebar":"tutorialSidebar"},"tldraw-server/How it works":{"id":"tldraw-server/How it works","title":"How it works","description":"The terms Redis and Valkey are used here synonymously and should describe the used in-memory-database.","sidebar":"tutorialSidebar"},"tldraw-server/Local setup":{"id":"tldraw-server/Local setup","title":"Local setup","description":"To run tldraw locally:","sidebar":"tutorialSidebar"},"tldraw-server/Technical details":{"id":"tldraw-server/Technical details","title":"Technical details","description":"Introduction","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.78b1f89e.js b/assets/js/935f2afb.78b1f89e.js deleted file mode 100644 index 5130337..0000000 --- a/assets/js/935f2afb.78b1f89e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).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":{"tutorialSidebar":[{"type":"link","label":"Schulcloud Documentation","href":"/docs/intro","docId":"intro"},{"type":"category","label":"nuxt-client","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting Started","href":"/docs/nuxt-client/GettingStarted","docId":"nuxt-client/GettingStarted"},{"type":"link","label":"Project Structure","href":"/docs/nuxt-client/ProjectStructure","docId":"nuxt-client/ProjectStructure"},{"type":"link","label":"Code Conventions","href":"/docs/nuxt-client/CodeConventions","docId":"nuxt-client/CodeConventions"},{"type":"link","label":"Git Conventions","href":"/docs/nuxt-client/GitConventions","docId":"nuxt-client/GitConventions"},{"type":"link","label":"How To","href":"/docs/nuxt-client/HowTo","docId":"nuxt-client/HowTo"},{"type":"link","label":"Writing Tests","href":"/docs/nuxt-client/WritingTests","docId":"nuxt-client/WritingTests"},{"type":"link","label":"Accessibility (A11y)","href":"/docs/nuxt-client/Accessibility","docId":"nuxt-client/Accessibility"},{"type":"link","label":"Colors","href":"/docs/nuxt-client/Colors","docId":"nuxt-client/Colors"},{"type":"link","label":"Identifying and Resolving Circular Dependencies","href":"/docs/nuxt-client/IdentifyingAndResolvingCircularDependencies","docId":"nuxt-client/IdentifyingAndResolvingCircularDependencies"},{"type":"link","label":"Hints for Working","href":"/docs/nuxt-client/HintsForWorking","docId":"nuxt-client/HintsForWorking"},{"type":"link","label":"Component Development Guidelines","href":"/docs/nuxt-client/ComponentGuidelines","docId":"nuxt-client/ComponentGuidelines"}],"href":"/docs/category/nuxt-client"},{"type":"category","label":"schulcloud-client","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting started","href":"/docs/schulcloud-client/Getting started","docId":"schulcloud-client/Getting started"}],"href":"/docs/category/schulcloud-client"},{"type":"category","label":"schulcloud-server","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting started","href":"/docs/schulcloud-server/Getting started","docId":"schulcloud-server/Getting started"},{"type":"link","label":"API design","href":"/docs/schulcloud-server/Api","docId":"schulcloud-server/Api"},{"type":"category","label":"Coding-Guidelines","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Access legacy Code","href":"/docs/schulcloud-server/Coding-Guidelines/access-legacy-code","docId":"schulcloud-server/Coding-Guidelines/access-legacy-code"},{"type":"link","label":"Code Style","href":"/docs/schulcloud-server/Coding-Guidelines/code-style","docId":"schulcloud-server/Coding-Guidelines/code-style"},{"type":"link","label":"Configuration","href":"/docs/schulcloud-server/Coding-Guidelines/configuration","docId":"schulcloud-server/Coding-Guidelines/configuration"},{"type":"link","label":"Controller","href":"/docs/schulcloud-server/Coding-Guidelines/controllers","docId":"schulcloud-server/Coding-Guidelines/controllers"},{"type":"link","label":"Deprecation Workflow","href":"/docs/schulcloud-server/Coding-Guidelines/deprection-workflow","docId":"schulcloud-server/Coding-Guidelines/deprection-workflow"},{"type":"link","label":"Domain Object Validation","href":"/docs/schulcloud-server/Coding-Guidelines/domain-object-validation","docId":"schulcloud-server/Coding-Guidelines/domain-object-validation"},{"type":"link","label":"Event Handling","href":"/docs/schulcloud-server/Coding-Guidelines/event-handling","docId":"schulcloud-server/Coding-Guidelines/event-handling"},{"type":"link","label":"Exception Handling","href":"/docs/schulcloud-server/Coding-Guidelines/exception-handling","docId":"schulcloud-server/Coding-Guidelines/exception-handling"},{"type":"link","label":"Logging","href":"/docs/schulcloud-server/Coding-Guidelines/logging","docId":"schulcloud-server/Coding-Guidelines/logging"},{"type":"link","label":"Defining Entities","href":"/docs/schulcloud-server/Coding-Guidelines/micro-orm","docId":"schulcloud-server/Coding-Guidelines/micro-orm"},{"type":"link","label":"Implementation and usage of modules, submodule and barrel files in our project","href":"/docs/schulcloud-server/Coding-Guidelines/modules-submodules","docId":"schulcloud-server/Coding-Guidelines/modules-submodules"},{"type":"link","label":"Repositories","href":"/docs/schulcloud-server/Coding-Guidelines/repositories","docId":"schulcloud-server/Coding-Guidelines/repositories"},{"type":"link","label":"Testing","href":"/docs/schulcloud-server/Coding-Guidelines/testing","docId":"schulcloud-server/Coding-Guidelines/testing"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Git","href":"/docs/schulcloud-server/Development/git","docId":"schulcloud-server/Development/git"},{"type":"link","label":"ErWIn-IDM (Keycloak)","href":"/docs/schulcloud-server/Development/keycloak","docId":"schulcloud-server/Development/keycloak"},{"type":"link","label":"Rocket.Chat","href":"/docs/schulcloud-server/Development/rocket-chat","docId":"schulcloud-server/Development/rocket-chat"},{"type":"link","label":"VSCode","href":"/docs/schulcloud-server/Development/vs-code","docId":"schulcloud-server/Development/vs-code"}]},{"type":"link","label":"Migrations","href":"/docs/schulcloud-server/Migrations","docId":"schulcloud-server/Migrations"},{"type":"link","label":"Software Architecture","href":"/docs/schulcloud-server/architecture","docId":"schulcloud-server/architecture"},{"type":"category","label":"our nextjs modules","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Room Member Module","href":"/docs/schulcloud-server/our nextjs modules/room-member-module/","docId":"schulcloud-server/our nextjs modules/room-member-module/index"}]}],"href":"/docs/category/schulcloud-server"},{"type":"category","label":"e2e-system-tests","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Getting Started","href":"/docs/e2e-system-tests/GettingStarted","docId":"e2e-system-tests/GettingStarted"},{"type":"link","label":"Project Structure","href":"/docs/e2e-system-tests/ProjectStructure","docId":"e2e-system-tests/ProjectStructure"},{"type":"link","label":"Code Conventions","href":"/docs/e2e-system-tests/CodeConventions","docId":"e2e-system-tests/CodeConventions"},{"type":"link","label":"Tags","href":"/docs/e2e-system-tests/Tags","docId":"e2e-system-tests/Tags"}],"href":"/docs/category/e2e-system-tests"},{"type":"category","label":"How to update the docs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Create a Page","href":"/docs/How to update the docs/create-a-page","docId":"How to update the docs/create-a-page"},{"type":"link","label":"Create a Document","href":"/docs/How to update the docs/create-a-document","docId":"How to update the docs/create-a-document"},{"type":"link","label":"Create a Blog Post","href":"/docs/How to update the docs/create-a-blog-post","docId":"How to update the docs/create-a-blog-post"},{"type":"link","label":"Markdown Features","href":"/docs/How to update the docs/markdown-features","docId":"How to update the docs/markdown-features"},{"type":"link","label":"Deploy your site","href":"/docs/How to update the docs/deploy-your-site","docId":"How to update the docs/deploy-your-site"},{"type":"link","label":"Congratulations!","href":"/docs/How to update the docs/congratulations","docId":"How to update the docs/congratulations"}],"href":"/docs/category/how-to-update-the-docs"},{"type":"category","label":"Informations","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Detect Dependency Cycles","href":"/docs/Informations/detect-dependency-cycles","docId":"Informations/detect-dependency-cycles"}]},{"type":"category","label":"services","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"etherpad","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How it works","href":"/docs/services/etherpad/How it works","docId":"services/etherpad/How it works"},{"type":"link","label":"Local Setup","href":"/docs/services/etherpad/Local setup","docId":"services/etherpad/Local setup"}]},{"type":"category","label":"tldraw","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How it works","href":"/docs/services/tldraw/How it works","docId":"services/tldraw/How it works"},{"type":"link","label":"Local setup","href":"/docs/services/tldraw/Local setup","docId":"services/tldraw/Local setup"},{"type":"link","label":"Technical details","href":"/docs/services/tldraw/Technical details","docId":"services/tldraw/Technical details"}]}]},{"type":"category","label":"syncronizations","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"TSP","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Architecture","href":"/docs/syncronizations/TSP/Architecture","docId":"syncronizations/TSP/Architecture"},{"type":"link","label":"How it works","href":"/docs/syncronizations/TSP/How it works","docId":"syncronizations/TSP/How it works"}]}]}]},"docs":{"e2e-system-tests/CodeConventions":{"id":"e2e-system-tests/CodeConventions","title":"Code Conventions","description":"This guide provides coding conventions and best practices for writing feature files, naming folders, files, methods, and step definitions. Following these conventions will ensure consistency and maintainability across the test framework.","sidebar":"tutorialSidebar"},"e2e-system-tests/GettingStarted":{"id":"e2e-system-tests/GettingStarted","title":"Getting Started","description":"This section provides instructions for setting up the Cypress-Cucumber test environment to ensure a smooth onboarding process.","sidebar":"tutorialSidebar"},"e2e-system-tests/ProjectStructure":{"id":"e2e-system-tests/ProjectStructure","title":"Project Structure","description":"Understanding the project directory layout will help you navigate and manage the Cypress-Cucumber E2E test framework effectively. This section provides a detailed breakdown of the folder structure and the purpose of each component.","sidebar":"tutorialSidebar"},"e2e-system-tests/Tags":{"id":"e2e-system-tests/Tags","title":"Tags","description":"This section explains the tagging system used for Cypress and Cucumber tests. Tags help categorize and selectively run tests based on environments, test stability, or purpose.","sidebar":"tutorialSidebar"},"How to update the docs/congratulations":{"id":"How to update the docs/congratulations","title":"Congratulations!","description":"You have just learned the basics of Docusaurus and made some changes to the initial template.","sidebar":"tutorialSidebar"},"How to update the docs/create-a-blog-post":{"id":"How to update the docs/create-a-blog-post","title":"Create a Blog Post","description":"Docusaurus creates a page for each blog post, but also a blog index page, a tag system, an RSS feed...","sidebar":"tutorialSidebar"},"How to update the docs/create-a-document":{"id":"How to update the docs/create-a-document","title":"Create a Document","description":"Documents are groups of pages connected through:","sidebar":"tutorialSidebar"},"How to update the docs/create-a-page":{"id":"How to update the docs/create-a-page","title":"Create a Page","description":"Add Markdown or React files to src/pages to create a standalone page:","sidebar":"tutorialSidebar"},"How to update the docs/deploy-your-site":{"id":"How to update the docs/deploy-your-site","title":"Deploy your site","description":"Docusaurus is a static-site-generator (also called Jamstack).","sidebar":"tutorialSidebar"},"How to update the docs/markdown-features":{"id":"How to update the docs/markdown-features","title":"Markdown Features","description":"Docusaurus supports Markdown and a few additional features.","sidebar":"tutorialSidebar"},"Informations/detect-dependency-cycles":{"id":"Informations/detect-dependency-cycles","title":"Detect Dependency Cycles","description":"You can use following package and command to detect dependency cycles in code.","sidebar":"tutorialSidebar"},"intro":{"id":"intro","title":"Schulcloud Documentation","description":"The schulcloud consists of many repositories.","sidebar":"tutorialSidebar"},"nuxt-client/Accessibility":{"id":"nuxt-client/Accessibility","title":"Accessibility (A11y)","description":"We want to make sure that our product can be used by anyone.","sidebar":"tutorialSidebar"},"nuxt-client/CodeConventions":{"id":"nuxt-client/CodeConventions","title":"Code Conventions","description":"- Code Conventions","sidebar":"tutorialSidebar"},"nuxt-client/Colors":{"id":"nuxt-client/Colors","title":"Colors","description":"In the Material Design system (the foundation of our component library), colors and color schemes are used to create a visual hierarchy, direct focus, and enhance the user experience.","sidebar":"tutorialSidebar"},"nuxt-client/ComponentGuidelines":{"id":"nuxt-client/ComponentGuidelines","title":"Component Development Guidelines","description":"HTML is not a string","sidebar":"tutorialSidebar"},"nuxt-client/GettingStarted":{"id":"nuxt-client/GettingStarted","title":"Getting Started","description":"Development Setup","sidebar":"tutorialSidebar"},"nuxt-client/GitConventions":{"id":"nuxt-client/GitConventions","title":"Git Conventions","description":"Each change should be done in a Ticket (no matter how small).","sidebar":"tutorialSidebar"},"nuxt-client/HintsForWorking":{"id":"nuxt-client/HintsForWorking","title":"Hints for Working","description":"Working with Material Design Icons","sidebar":"tutorialSidebar"},"nuxt-client/HowTo":{"id":"nuxt-client/HowTo","title":"How To","description":"Collection of instructions on how to do certain things:","sidebar":"tutorialSidebar"},"nuxt-client/IdentifyingAndResolvingCircularDependencies":{"id":"nuxt-client/IdentifyingAndResolvingCircularDependencies","title":"Identifying and Resolving Circular Dependencies","description":"What is a circular dependency?","sidebar":"tutorialSidebar"},"nuxt-client/ProjectStructure":{"id":"nuxt-client/ProjectStructure","title":"Project Structure","description":"Filenames","sidebar":"tutorialSidebar"},"nuxt-client/WritingTests":{"id":"nuxt-client/WritingTests","title":"Writing Tests","description":"How to write valuable, reliable tests, that are easy to maintain.","sidebar":"tutorialSidebar"},"schulcloud-client/Getting started":{"id":"schulcloud-client/Getting started","title":"Getting started","description":"Make sure to have the following software installed","sidebar":"tutorialSidebar"},"schulcloud-server/Api":{"id":"schulcloud-server/Api","title":"API design","description":"nest.js","sidebar":"tutorialSidebar"},"schulcloud-server/architecture":{"id":"schulcloud-server/architecture","title":"Software Architecture","description":"Goals","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/access-legacy-code":{"id":"schulcloud-server/Coding-Guidelines/access-legacy-code","title":"Access legacy Code","description":"Access Feathers Service from NestJS","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/code-style":{"id":"schulcloud-server/Coding-Guidelines/code-style","title":"Code Style","description":"Function","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/configuration":{"id":"schulcloud-server/Coding-Guidelines/configuration","title":"Configuration","description":"The Configuration Management consists of three layers working together.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/controllers":{"id":"schulcloud-server/Coding-Guidelines/controllers","title":"Controller","description":"A modules api layer is defined within of controllers.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/deprection-workflow":{"id":"schulcloud-server/Coding-Guidelines/deprection-workflow","title":"Deprecation Workflow","description":"When to use 2 step migration","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/domain-object-validation":{"id":"schulcloud-server/Coding-Guidelines/domain-object-validation","title":"Domain Object Validation","description":"If you need to validate a domain object, please write an independent class, so that the domain object itself, its repo and services can reuse it.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/event-handling":{"id":"schulcloud-server/Coding-Guidelines/event-handling","title":"Event Handling","description":"Internal Events are used as a mechanism for Dependency Inversion.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/exception-handling":{"id":"schulcloud-server/Coding-Guidelines/exception-handling","title":"Exception Handling","description":"exception hierarchy","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/logging":{"id":"schulcloud-server/Coding-Guidelines/logging","title":"Logging","description":"For logging use the Logger, exported by the logger module. It encapsulates a Winston logger. Its injection scope is transient, so you can set a context when you inject it.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/micro-orm":{"id":"schulcloud-server/Coding-Guidelines/micro-orm","title":"Defining Entities","description":"When defining entities with MikroORM (Version 5), the following should be considered:","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/modules-submodules":{"id":"schulcloud-server/Coding-Guidelines/modules-submodules","title":"Implementation and usage of modules, submodule and barrel files in our project","description":"In this guide, we\'ll cover how to use modules, submodules and barrel files in our project. These concepts help you organize your code into separate files and directories, making it easier to manage and maintain.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/repositories":{"id":"schulcloud-server/Coding-Guidelines/repositories","title":"Repositories","description":"The repository is responsible to provide domain objects for the domain layer. Typically, it does so by accessing a database.","sidebar":"tutorialSidebar"},"schulcloud-server/Coding-Guidelines/testing":{"id":"schulcloud-server/Coding-Guidelines/testing","title":"Testing","description":"Automated testing is the essential part of the software development process.","sidebar":"tutorialSidebar"},"schulcloud-server/Development/git":{"id":"schulcloud-server/Development/git","title":"Git","description":"Branch name conventions","sidebar":"tutorialSidebar"},"schulcloud-server/Development/keycloak":{"id":"schulcloud-server/Development/keycloak","title":"ErWIn-IDM (Keycloak)","description":"ErWIn-IDM, namely Keycloak, will be the future Identity Management System (IDM) for the dBildungscloud. Keycloak","sidebar":"tutorialSidebar"},"schulcloud-server/Development/rocket-chat":{"id":"schulcloud-server/Development/rocket-chat","title":"Rocket.Chat","description":"Start Mongodb","sidebar":"tutorialSidebar"},"schulcloud-server/Development/vs-code":{"id":"schulcloud-server/Development/vs-code","title":"VSCode","description":"Launch scripts","sidebar":"tutorialSidebar"},"schulcloud-server/Getting started":{"id":"schulcloud-server/Getting started","title":"Getting started","description":"Make sure to have the following software installed","sidebar":"tutorialSidebar"},"schulcloud-server/Migrations":{"id":"schulcloud-server/Migrations","title":"Migrations","description":"Migrations for server database","sidebar":"tutorialSidebar"},"schulcloud-server/our nextjs modules/room-member-module/index":{"id":"schulcloud-server/our nextjs modules/room-member-module/index","title":"Room Member Module","description":"The Room Member module manages the association between users and rooms, handling permissions and roles within rooms. This module is designed to be injected into the Room module for managing user access and roles within rooms.","sidebar":"tutorialSidebar"},"services/etherpad/How it works":{"id":"services/etherpad/How it works","title":"How it works","description":"Configuration","sidebar":"tutorialSidebar"},"services/etherpad/Local setup":{"id":"services/etherpad/Local setup","title":"Local Setup","description":"Running the Etherpad server","sidebar":"tutorialSidebar"},"services/tldraw/How it works":{"id":"services/tldraw/How it works","title":"How it works","description":"Configuration","sidebar":"tutorialSidebar"},"services/tldraw/Local setup":{"id":"services/tldraw/Local setup","title":"Local setup","description":"To run tldraw locally:","sidebar":"tutorialSidebar"},"services/tldraw/Technical details":{"id":"services/tldraw/Technical details","title":"Technical details","description":"Backend","sidebar":"tutorialSidebar"},"syncronizations/TSP/Architecture":{"id":"syncronizations/TSP/Architecture","title":"Architecture","description":"TspSyncStrategy","sidebar":"tutorialSidebar"},"syncronizations/TSP/How it works":{"id":"syncronizations/TSP/How it works","title":"How it works","description":"Configuration","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/a6e79240.4976e692.js b/assets/js/a6e79240.4976e692.js deleted file mode 100644 index 4bd5979..0000000 --- a/assets/js/a6e79240.4976e692.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[6074],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=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 a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=c(n),m=o,d=u["".concat(l,".").concat(m)]||u[m]||h[m]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var r=n(7462),o=(n(7294),n(3905));const a={},i="How it works",s={unversionedId:"syncronizations/TSP/How it works",id:"syncronizations/TSP/How it works",title:"How it works",description:"Configuration",source:"@site/docs/syncronizations/TSP/How it works.md",sourceDirName:"syncronizations/TSP",slug:"/syncronizations/TSP/How it works",permalink:"/docs/syncronizations/TSP/How it works",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/syncronizations/TSP/How it works.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Architecture",permalink:"/docs/syncronizations/TSP/Architecture"}},l={},c=[{value:"Configuration",id:"configuration",level:2},{value:"Sync console",id:"sync-console",level:2},{value:"Usage",id:"usage",level:3},{value:"TSP synchronization",id:"tsp-synchronization",level:3}],p={toc:c},u="wrapper";function h(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"how-it-works"},"How it works"),(0,o.kt)("h2",{id:"configuration"},"Configuration"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"FEATURE_TSP_SYNC_ENABLED - Activates the sync strategy inside the sync console")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"WITH_TSP_SYNC - Activates the cronjob in Kubernetes")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_API_CLIENT_BASE_URL - Base URL for the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_API_TOKEN_LIFETIME_MS - Lifetime of the access token for the TSP API in milliseconds")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_SCHOOL_LIMIT - The amount of schools the sync handles at once")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_SCHOOL_DAYS_TO_FETCH - The amount of days for which the sync fetches schools from the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_DATA_LIMIT - The amount of school data updates the sync handles at once")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_DATA_DAYS_TO_FETCH - The amount of days for which the sync fetches school data from the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"FEATURE_TSP_MIGRATION_ENABLED - Activates the migration of TSP users within the sync")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_MIGRATION_LIMIT - The amount of users the sync migrates at once"))),(0,o.kt)("h2",{id:"sync-console"},"Sync console"),(0,o.kt)("p",null,"This is a console application that allows you to start the synchronization process for different sources."),(0,o.kt)("h3",{id:"usage"},"Usage"),(0,o.kt)("p",null,"To start the synchronization process, run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"npm run nest:start:console sync run \n")),(0,o.kt)("p",null,"Where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is the name of the system you want to start the synchronization for. The currently available systems are:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"tsp")," - Synchronize Th\xfcringer Schulportal.")),(0,o.kt)("p",null,"If the target is not provided, the synchronization will not start and the available targets will be displayed in an error message."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"{\n message: 'Either synchronization is not activated or the target entered is invalid',\n data: { enteredTarget: 'tsp', availableTargets: { TSP: 'tsp' }}\n}\n")),(0,o.kt)("h3",{id:"tsp-synchronization"},"TSP synchronization"),(0,o.kt)("p",null,"The TSP synchronization is controlled with the feature flag ",(0,o.kt)("inlineCode",{parentName:"p"},"FEATURE_TSP_SYNC_ENABLED"),"."))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a6e79240.b9af744f.js b/assets/js/a6e79240.b9af744f.js new file mode 100644 index 0000000..9b767fe --- /dev/null +++ b/assets/js/a6e79240.b9af744f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[6074],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=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 a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=c(n),m=o,d=u["".concat(l,".").concat(m)]||u[m]||h[m]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var r=n(7462),o=(n(7294),n(3905));const a={},i="How it works",s={unversionedId:"syncronizations/TSP/How it works",id:"syncronizations/TSP/How it works",title:"How it works",description:"Configuration",source:"@site/docs/syncronizations/TSP/How it works.md",sourceDirName:"syncronizations/TSP",slug:"/syncronizations/TSP/How it works",permalink:"/docs/syncronizations/TSP/How it works",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/syncronizations/TSP/How it works.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Architecture",permalink:"/docs/syncronizations/TSP/Architecture"},next:{title:"How it works",permalink:"/docs/tldraw-server/How it works"}},l={},c=[{value:"Configuration",id:"configuration",level:2},{value:"Sync console",id:"sync-console",level:2},{value:"Usage",id:"usage",level:3},{value:"TSP synchronization",id:"tsp-synchronization",level:3}],p={toc:c},u="wrapper";function h(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"how-it-works"},"How it works"),(0,o.kt)("h2",{id:"configuration"},"Configuration"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"FEATURE_TSP_SYNC_ENABLED - Activates the sync strategy inside the sync console")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"WITH_TSP_SYNC - Activates the cronjob in Kubernetes")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_API_CLIENT_BASE_URL - Base URL for the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_API_TOKEN_LIFETIME_MS - Lifetime of the access token for the TSP API in milliseconds")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_SCHOOL_LIMIT - The amount of schools the sync handles at once")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_SCHOOL_DAYS_TO_FETCH - The amount of days for which the sync fetches schools from the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_DATA_LIMIT - The amount of school data updates the sync handles at once")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_DATA_DAYS_TO_FETCH - The amount of days for which the sync fetches school data from the TSP API")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"FEATURE_TSP_MIGRATION_ENABLED - Activates the migration of TSP users within the sync")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"TSP_SYNC_MIGRATION_LIMIT - The amount of users the sync migrates at once"))),(0,o.kt)("h2",{id:"sync-console"},"Sync console"),(0,o.kt)("p",null,"This is a console application that allows you to start the synchronization process for different sources."),(0,o.kt)("h3",{id:"usage"},"Usage"),(0,o.kt)("p",null,"To start the synchronization process, run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"npm run nest:start:console sync run \n")),(0,o.kt)("p",null,"Where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is the name of the system you want to start the synchronization for. The currently available systems are:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"tsp")," - Synchronize Th\xfcringer Schulportal.")),(0,o.kt)("p",null,"If the target is not provided, the synchronization will not start and the available targets will be displayed in an error message."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"{\n message: 'Either synchronization is not activated or the target entered is invalid',\n data: { enteredTarget: 'tsp', availableTargets: { TSP: 'tsp' }}\n}\n")),(0,o.kt)("h3",{id:"tsp-synchronization"},"TSP synchronization"),(0,o.kt)("p",null,"The TSP synchronization is controlled with the feature flag ",(0,o.kt)("inlineCode",{parentName:"p"},"FEATURE_TSP_SYNC_ENABLED"),"."))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e68d14cf.4dcf5e70.js b/assets/js/e68d14cf.4dcf5e70.js new file mode 100644 index 0000000..9f5e895 --- /dev/null +++ b/assets/js/e68d14cf.4dcf5e70.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[604],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>h});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var o=n.createContext({}),d=function(e){var t=n.useContext(o),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},p=function(e){var t=d(e.components);return n.createElement(o.Provider,{value:t},e.children)},c="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,s=e.originalType,o=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),c=d(a),u=r,h=c["".concat(o,".").concat(u)]||c[u]||m[u]||s;return a?n.createElement(h,i(i({ref:t},p),{},{components:a})):n.createElement(h,i({ref:t},p))}));function h(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var s=a.length,i=new Array(s);i[0]=u;var l={};for(var o in t)hasOwnProperty.call(t,o)&&(l[o]=t[o]);l.originalType=e,l[c]="string"==typeof e?e:r,i[1]=l;for(var d=2;d{a.r(t),a.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var n=a(7462),r=(a(7294),a(3905));const s={},i="Technical details",l={unversionedId:"tldraw-server/Technical details",id:"tldraw-server/Technical details",title:"Technical details",description:"Introduction",source:"@site/docs/tldraw-server/Technical details.md",sourceDirName:"tldraw-server",slug:"/tldraw-server/Technical details",permalink:"/docs/tldraw-server/Technical details",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/tldraw-server/Technical details.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Local setup",permalink:"/docs/tldraw-server/Local setup"}},o={},d=[{value:"Introduction",id:"introduction",level:2},{value:"How tldraw Uses Redis and S3 Storage:",id:"how-tldraw-uses-redis-and-s3-storage",level:3},{value:"Example Scenario:",id:"example-scenario",level:3},{value:"Conclusion:",id:"conclusion",level:3},{value:"Backend",id:"backend",level:2},{value:"Deployments",id:"deployments",level:3},{value:"Tldraw-server code structure",id:"tldraw-server-code-structure",level:3},{value:"Frontend",id:"frontend",level:2},{value:"Key Files",id:"key-files",level:3},{value:"Frontend Technologies",id:"frontend-technologies",level:3},{value:"State Managment",id:"state-managment",level:3},{value:"useTldrawUiSanitizer.ts",id:"usetldrawuisanitizerts",level:4},{value:"Event Handling",id:"event-handling",level:4},{value:"Useful links",id:"useful-links",level:4}],p={toc:d},c="wrapper";function m(e){let{components:t,...a}=e;return(0,r.kt)(c,(0,n.Z)({},p,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"technical-details"},"Technical details"),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,"In tldraw-server, ",(0,r.kt)("strong",{parentName:"p"},"Yjs"),", ",(0,r.kt)("strong",{parentName:"p"},"Redis")," and ",(0,r.kt)("strong",{parentName:"p"},"S3 storage")," are integrated to support collaborative drawing features, data synchronization, and persistent storage in a scalable and efficient manner. The combination of ",(0,r.kt)("strong",{parentName:"p"},"Yjs")," (used for collaborative editing), ",(0,r.kt)("strong",{parentName:"p"},"Redis")," (for real-time data synchronization), and ",(0,r.kt)("strong",{parentName:"p"},"S3")," (for file storage) enables the platform to handle complex collaborative interactions and large-scale, persistent storage of drawing data."),(0,r.kt)("h3",{id:"how-tldraw-uses-redis-and-s3-storage"},"How tldraw Uses Redis and S3 Storage:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"Real-time Collaboration with Yjs:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Yjs")," is the backbone of real-time collaboration in tldraw. It provides a ",(0,r.kt)("strong",{parentName:"li"},"CRDT-based (Conflict-free Replicated Data Type)")," framework for handling shared documents where changes made by one user are automatically and consistently synchronized across all other users in the same session."),(0,r.kt)("li",{parentName:"ul"},"In tldraw, the ",(0,r.kt)("strong",{parentName:"li"},"drawing canvas")," or ",(0,r.kt)("strong",{parentName:"li"},"document")," is represented as a ",(0,r.kt)("strong",{parentName:"li"},"Yjs document"),". Users can draw shapes, lines, text, or modify the canvas in real time."),(0,r.kt)("li",{parentName:"ul"},"The ",(0,r.kt)("strong",{parentName:"li"},"Yjs document")," tracks all changes in the form of small, incremental edits. These edits could be changes to the position of objects, the creation of new objects (e.g., shapes or lines), or modification of existing elements.")))),(0,r.kt)("p",null,". ",(0,r.kt)("strong",{parentName:"p"},"Redis for Real-Time Data Synchronization:")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Redis")," is used to store and synchronize these Yjs documents across multiple users in real time. "),(0,r.kt)("li",{parentName:"ul"},"Redis, being a fast in-memory key-value store, provides low-latency updates that are crucial for real-time collaboration. It is used for:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Broadcasting updates"),": When one user makes a change, Yjs sends that change to the Redis server, which then distributes the change to all other connected users."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Data persistence"),": Changes are stored in Redis and can be fetched by other users at any time to maintain consistency."))),(0,r.kt)("li",{parentName:"ul"},"The use of ",(0,r.kt)("strong",{parentName:"li"},"Redis Pub/Sub")," allows different instances of the tldraw application to subscribe to channels. When one user makes a change, the Redis system publishes the change, and other users (who are subscribed to that document) get updated immediately.")),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"S3 Storage for Persistent and Large-Scale File Storage:")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"While Redis ensures real-time synchronization and collaboration, ",(0,r.kt)("strong",{parentName:"li"},"S3")," (Amazon Simple Storage Service) is used for ",(0,r.kt)("strong",{parentName:"li"},"persistent storage")," of larger files or data that need to be saved across sessions."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"S3")," is highly scalable and can store large amounts of data. For tldraw, S3 is primarily used for:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Storing canvases and drawings"),": While ",(0,r.kt)("strong",{parentName:"li"},"Redis")," handles real-time data synchronization and storage of changes, the worker service is responsible for ",(0,r.kt)("strong",{parentName:"li"},"periodically persisting")," the state of the collaborative canvas to ",(0,r.kt)("strong",{parentName:"li"},"S3 storage"),"."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"S3 as a file store"),": Unlike Redis, which is an in-memory store designed for fast access and transient data, S3 is optimized for storing larger data in a persistent manner. This makes it suitable for storing media files, large canvas snapshots, and other assets that don't need to be constantly updated in real-time."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Integration Between Redis and S3:")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Redis")," and ",(0,r.kt)("strong",{parentName:"li"},"S3")," serve different but complementary purposes:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Redis")," handles ",(0,r.kt)("strong",{parentName:"li"},"real-time synchronization")," of drawing changes and interactions, ensuring that users see each other's edits in near real-time."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"S3")," handles ",(0,r.kt)("strong",{parentName:"li"},"long-term storage")," and ",(0,r.kt)("strong",{parentName:"li"},"backup")," of the drawings or canvases themselves. For example, when a user closes the app or saves their session, the drawing data is saved to S3."))),(0,r.kt)("li",{parentName:"ul"},"The worker service will save snapshots of the collaborative document or canvas to S3 periodically, ensuring that the state of the canvas is preserved even if a user disconnects or the server restarts."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"How tldraw's Workflow Would Look Using Redis and S3:")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Step 1: Collaborative Drawing Session")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Users interact with the tldraw canvas, making real-time changes (drawing shapes, text, etc.)."),(0,r.kt)("li",{parentName:"ul"},"The changes are immediately propagated through ",(0,r.kt)("strong",{parentName:"li"},"Yjs")," and ",(0,r.kt)("strong",{parentName:"li"},"Redis"),". Redis stores these changes in memory and broadcasts them to other users."),(0,r.kt)("li",{parentName:"ul"},"Each user's drawing operations are synchronized, so everyone sees the same live canvas."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Step 2: Saving the Canvas")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"On a regular basis the worker service will send a ",(0,r.kt)("strong",{parentName:"li"},"snapshot of the canvas")," (or the entire Yjs document) to ",(0,r.kt)("strong",{parentName:"li"},"S3"),". This can include data about the shapes, their positions, colors, and any other relevant canvas data."),(0,r.kt)("li",{parentName:"ul"},"The snapshot can be stored as a ",(0,r.kt)("strong",{parentName:"li"},"JSON object"),", an image, or another format, depending on how tldraw chooses to serialize the data."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Step 3: Retrieving Saved Data")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"When a user returns to the drawing session or opens the application at a later time, the application queries ",(0,r.kt)("strong",{parentName:"li"},"S3")," for the last saved canvas snapshot."),(0,r.kt)("li",{parentName:"ul"},"Once retrieved, the snapshot is loaded back into the application, allowing users to continue editing from where they left off."),(0,r.kt)("li",{parentName:"ul"},"Redis can be used in the background to ensure that any new changes made by users are synchronized in real time while they are working on the canvas."))))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Scalability and Fault Tolerance:")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Redis Scaling"),": As we are using Valkey, by default there will only be one primary Valkey instance and we will have two replica instances ready to jump in once the primary instance fails. But these two replica sets make sure, that Valkey is always available."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"S3 Scaling"),": S3 is designed to scale automatically and handle large amounts of storage without performance degradation. This makes it ideal for storing large or numerous drawing assets, like high-resolution images or full snapshots of large canvases."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Tldraw-server Scaling"),": So far the number of pods the tldraw-server is deployed on is fixed and no load based scaling is applied so far.")))),(0,r.kt)("h3",{id:"example-scenario"},"Example Scenario:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"User A")," and ",(0,r.kt)("strong",{parentName:"li"},"User B")," start a collaborative session in tldraw, and they can see each other's updates in real time (thanks to Redis)."),(0,r.kt)("li",{parentName:"ul"},"After some time, the worker service saves the drawing to S3, and now the drawing is stored in S3 as a persistent snapshot."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"User B"),", who was not connected when the session ended, can later load the canvas from S3, where the most recent version is stored."),(0,r.kt)("li",{parentName:"ul"},"Meanwhile, as new users join the session, ",(0,r.kt)("strong",{parentName:"li"},"Redis")," continues to handle the real-time synchronization of the drawing, ensuring smooth interaction.")),(0,r.kt)("h3",{id:"conclusion"},"Conclusion:"),(0,r.kt)("p",null,"In ",(0,r.kt)("strong",{parentName:"p"},"tldraw"),", ",(0,r.kt)("strong",{parentName:"p"},"Redis")," and ",(0,r.kt)("strong",{parentName:"p"},"S3")," are integrated to deliver a collaborative and scalable experience. Redis ensures real-time synchronization of drawing changes among multiple users, while S3 provides persistent and scalable storage for canvas data. This combination allows tldraw to offer seamless collaboration, persistent storage, and fault-tolerant handling of large-scale data."),(0,r.kt)("h2",{id:"backend"},"Backend"),(0,r.kt)("h3",{id:"deployments"},"Deployments"),(0,r.kt)("p",null,"Tldraw is deployed as a separate application from schoulcloud-server and consists of the following deployments :"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"tldraw-server-deployment - deployment for tldraw-server's instances."),(0,r.kt)("li",{parentName:"ul"},"tldraw-worker-deployment - deployment for worker's instances."),(0,r.kt)("li",{parentName:"ul"},"tldraw-client-deployment - deployment for tldraw-client's instances.")),(0,r.kt)("h3",{id:"tldraw-server-code-structure"},"Tldraw-server code structure"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"tldraw-config.controller.ts - controller that exposes tldraw server configuration to be used by the tldraw client."),(0,r.kt)("li",{parentName:"ul"},"tldraw-document.controller.ts - controller that expose HTTP deletion method outside the tldraw-server application."),(0,r.kt)("li",{parentName:"ul"},"tldraw-document.service.ts - service used by TldrawDocumentController."),(0,r.kt)("li",{parentName:"ul"},"redis.service.ts - encapsulates the logic for creating and managing Redis instances, supporting both standalone and sentinel configurations, and integrates seamlessly with the NestJS framework."),(0,r.kt)("li",{parentName:"ul"},"ioredis.adapter.ts - encapsulates the logic for interacting with Redis, including defining custom commands and subscribing to channels. It leverages the ioredis library and integrates with the application's configuration and logging systems to provide a robust and flexible Redis adapter."),(0,r.kt)("li",{parentName:"ul"},"api.service.ts - API service for Redis."),(0,r.kt)("li",{parentName:"ul"},"ws.service.ts - Responsibe for Redis communication."),(0,r.kt)("li",{parentName:"ul"},"metrics.service.ts - service resonsible for storing application-level metrics."),(0,r.kt)("li",{parentName:"ul"},"worker.service.ts - responsible for persisting the current state of changed tldraw documents into the file storage.")),(0,r.kt)("p",null,"On the backend side we are also using Yjs library to store tldraw board in memory and to calculate diffs after the board is changed."),(0,r.kt)("h2",{id:"frontend"},"Frontend"),(0,r.kt)("h3",{id:"key-files"},"Key Files"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"stores/setup.ts \u2013 this file provides a real-time collaboration environment for a drawing application using the WebSocket and Yjs libraries."),(0,r.kt)("li",{parentName:"ul"},"hooks/useMultiplayerState.ts \u2013 custom hook for managing multiplayer state."),(0,r.kt)("li",{parentName:"ul"},"App.tsx \u2013 main application component integrating Tldraw and multiplayer state.")),(0,r.kt)("h3",{id:"frontend-technologies"},"Frontend Technologies"),(0,r.kt)("p",null,"The frontend of the project is built using React and leverages various libraries and tools for enhanced functionality. Here is an overview of the key frontend technologies:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"React: A JavaScript library for building user interfaces."),(0,r.kt)("li",{parentName:"ul"},"Yjs: A real-time collaboration framework for synchronizing shared state."),(0,r.kt)("li",{parentName:"ul"},"Tldraw: A library for drawing functionalities in the application. We use the old version of tldraw: ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/tldraw/tldraw-v1"},"https://github.com/tldraw/tldraw-v1"),", after the tldraw team releases the official update of the new version, we will work on the new version and integrate it with the needs of our users. ")),(0,r.kt)("h3",{id:"state-managment"},"State Managment"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Yjs is integrated into the project for real-time collaboration. The central state (shapes, bindings, assets) is managed using Yjs maps."),(0,r.kt)("li",{parentName:"ol"},"store.ts handles the configuration of Yjs, WebSocket connections, and provides centralized maps for shapes, bindings, and assets"),(0,r.kt)("li",{parentName:"ol"},"useMultiplayerState.ts -This hook manages the multiplayer state, including loading rooms, handling file system operations, and updating Yjs maps:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Mounting and handling changes in Tldraw App."),(0,r.kt)("li",{parentName:"ul"},"Presence management and user updates."),(0,r.kt)("li",{parentName:"ul"},"File system operations like opening and saving projects.")))),(0,r.kt)("h4",{id:"usetldrawuisanitizerts"},"useTldrawUiSanitizer.ts"),(0,r.kt)("p",null,"This hook is designed to observe changes in the DOM, specifically targeting certain buttons and a horizontal rule (< hr>), and hides them if they match a specific ID pattern. We hide this elements and left just only Language and Keyboard shortcuts."),(0,r.kt)("h4",{id:"event-handling"},"Event Handling"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"onMount: Handles mounting of the Tldraw app."),(0,r.kt)("li",{parentName:"ul"},"onChangePage: Manages page changes and updates Yjs maps."),(0,r.kt)("li",{parentName:"ul"},"onUndo and onRedo: Handle undo and redo operations."),(0,r.kt)("li",{parentName:"ul"},"onChangePresence: Manages presence changes in the collaborative environment."),(0,r.kt)("li",{parentName:"ul"},"onAssetCreate: This function is triggered when a user attempts to upload an asset (like an image or a file).")),(0,r.kt)("h4",{id:"useful-links"},"Useful links"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://tldraw.dev/"},"https://tldraw.dev/")," - documentation for the new version of tldraw")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://old.tldraw.com/"},"https://old.tldraw.com/")," - tldraw live application")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/tldraw/tldraw-v1"},"https://github.com/tldraw/tldraw-v1")," - tldraw v1 repo")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/yjs/y-redis"},"https://github.com/yjs/y-redis")," - code from this package was used to add Redis as a persistence to tldraw")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://discord.com/invite/SBBEVCA4PG"},"https://discord.com/invite/SBBEVCA4PG")," discord channel with open questions and answers")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://grafana.dbildungscloud.dev/d/b6b28b2b-3129-4772-8102-e32981d2c2e3/devops-tldraw-metrics?orgId=1&refresh=1m&var-source=sc-dev-dbc&var-env=main&var-env=tldraw-debugging"},"https://grafana.dbildungscloud.dev/d/b6b28b2b-3129-4772-8102-e32981d2c2e3/devops-tldraw-metrics?orgId=1&refresh=1m&var-source=sc-dev-dbc&var-env=main&var-env=tldraw-debugging")," - grafana v")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://grafana.dbildungscloud.org/d/b6b28b2b-3129-4772-8102-e32981d2c2e0/devops-tldraw?orgId=1&from=now-6h&to=now&refresh=1m"},"https://grafana.dbildungscloud.org/d/b6b28b2b-3129-4772-8102-e32981d2c2e0/devops-tldraw?orgId=1&from=now-6h&to=now&refresh=1m")," - grafana metrics")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/nimeshnayaju/yjs-tldraw"},"https://github.com/nimeshnayaju/yjs-tldraw")," - yjs with tldraw POC")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/yjs/y-websocket/tree/master/bin"},"https://github.com/yjs/y-websocket/tree/master/bin")," - yjs/y-websocket repo")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/erdtool/yjs-scalable-ws-backend/tree/main"},"https://github.com/erdtool/yjs-scalable-ws-backend/tree/main")," - Yjs scalable WS backend with redis example")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://teamchat.dbildungscloud.de/channel/G9hJWv92zXEESKK3X"},"https://teamchat.dbildungscloud.de/channel/G9hJWv92zXEESKK3X"),' - rocketchat discussion "tldraw syncronisation for release again"')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://teamchat.dbildungscloud.de/group/SagK4sCyujhu6yZr8"},"https://teamchat.dbildungscloud.de/group/SagK4sCyujhu6yZr8"),' - rocketchat discussion "Tldraw deployment"s'))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ef5d9dc5.5eb6dae8.js b/assets/js/ef5d9dc5.5eb6dae8.js deleted file mode 100644 index 21b7d4b..0000000 --- a/assets/js/ef5d9dc5.5eb6dae8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[4028],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>h});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function i(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var o=r.createContext({}),d=function(e){var t=r.useContext(o),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},c=function(e){var t=d(e.components);return r.createElement(o.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,s=e.originalType,o=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=d(a),m=n,h=p["".concat(o,".").concat(m)]||p[m]||u[m]||s;return a?r.createElement(h,i(i({ref:t},c),{},{components:a})):r.createElement(h,i({ref:t},c))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var s=a.length,i=new Array(s);i[0]=m;var l={};for(var o in t)hasOwnProperty.call(t,o)&&(l[o]=t[o]);l.originalType=e,l[p]="string"==typeof e?e:n,i[1]=l;for(var d=2;d{a.r(t),a.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var r=a(7462),n=(a(7294),a(3905));const s={},i="Technical details",l={unversionedId:"services/tldraw/Technical details",id:"services/tldraw/Technical details",title:"Technical details",description:"Backend",source:"@site/docs/services/tldraw/Technical details.md",sourceDirName:"services/tldraw",slug:"/services/tldraw/Technical details",permalink:"/docs/services/tldraw/Technical details",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/services/tldraw/Technical details.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Local setup",permalink:"/docs/services/tldraw/Local setup"},next:{title:"Architecture",permalink:"/docs/syncronizations/TSP/Architecture"}},o={},d=[{value:"Backend",id:"backend",level:2},{value:"Tldraw-server code structure",id:"tldraw-server-code-structure",level:3},{value:"Frontend",id:"frontend",level:2},{value:"Key Files",id:"key-files",level:3},{value:"Frontend Technologies",id:"frontend-technologies",level:3},{value:"State Managment",id:"state-managment",level:3},{value:"useTldrawUiSanitizer.ts",id:"usetldrawuisanitizerts",level:4},{value:"Event Handling",id:"event-handling",level:4},{value:"Useful links",id:"useful-links",level:4}],c={toc:d},p="wrapper";function u(e){let{components:t,...a}=e;return(0,n.kt)(p,(0,r.Z)({},c,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"technical-details"},"Technical details"),(0,n.kt)("h2",{id:"backend"},"Backend"),(0,n.kt)("p",null,"We are using pure Web Sockets implementation to establish connection between client and server. The reason why we used pure websockets is because tldraw-client is using y-websockets from Yjs library, that does not connect with socket.io web sockets. We also have to implement broadcasting mechanism to provide stateless solution. To achive that goal we decided to use Redis. We used ioredis library to connect to our Redis instance. Everytime user make some changes at first it is handled to the server instance that he is connected to an then this change is send to the channel with the name of the board and servers that also operate that board are listening on this channel so they can recive messages from other servers and provide those changes to users that are connected to this pod. We added the same mechanism for awareness channel so every user from every pod can see other users cursours."),(0,n.kt)("p",null,"Tldraw is deployed as a separate application from schoulcloud-server working on the same namespace as schoulcloud-server. On the backend side we have added couple new resources:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"tldraw-deployment - deployment for tldraw-server's instances."),(0,n.kt)("li",{parentName:"ul"},"tldraw-server-svc - service for tldraw-service to communicate with tldraw-client (WS) and schoulcloud-server (management e.g. deletion of data)"),(0,n.kt)("li",{parentName:"ul"},"tldraw-svc-monitor - service to collect metrics from tldraw. Apart from typical metrics like request time we also added two application-level metrics:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"sc_tldraw_users - number of active users on boards"),(0,n.kt)("li",{parentName:"ul"},"sc_tldraw_boards - number of active boards"))),(0,n.kt)("li",{parentName:"ul"},"tldraw-ingress - for steering web external traffic to tldraw-server (for now management rules in tldraw-server-svc are closed from external clients) ")),(0,n.kt)("h3",{id:"tldraw-server-code-structure"},"Tldraw-server code structure"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"tldraw.ws.service.ts - main service responsible for establishing web socket connection as well as saving data to database. Responsibe for Redis communication."),(0,n.kt)("li",{parentName:"ul"},"tldraw.controller.ts - controller that expose HTTP deletion method outside the tldraw-server application."),(0,n.kt)("li",{parentName:"ul"},"tldraw.server.ts - service used by TldrawController."),(0,n.kt)("li",{parentName:"ul"},"y-mongodb.ts - main adapter to connect with mongodb, provides transaction mechanism, calucalate diffs between revision and to apply updates."),(0,n.kt)("li",{parentName:"ul"},"tldraw-board.repo.ts - repository object to connect TldrawWsService and YMongodb."),(0,n.kt)("li",{parentName:"ul"},"tldraw.repo.ts - repository used by TldrawService to find and delete boards from database."),(0,n.kt)("li",{parentName:"ul"},"ws-shared-doc.do.ts - main structure representing tldraw drawing during web socket communication. it holds all the web-socket addresses that are connected to this board, so we can inform all the connected clients about changes. "),(0,n.kt)("li",{parentName:"ul"},"tldraw-drawing.entity.ts - object representing tldraw drawingn entity in database."),(0,n.kt)("li",{parentName:"ul"},"metrics.service.ts - service resonsible for storing application-level metrics.")),(0,n.kt)("p",null,"On the backend side we are also using Yjs library to store tldraw board in memory and to calculate diffs after the board is changed."),(0,n.kt)("h2",{id:"frontend"},"Frontend"),(0,n.kt)("h3",{id:"key-files"},"Key Files"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"stores/setup.ts \u2013 this file provides a real-time collaboration environment for a drawing application using the WebSocket and Yjs libraries."),(0,n.kt)("li",{parentName:"ul"},"hooks/useMultiplayerState.ts \u2013 custom hook for managing multiplayer state."),(0,n.kt)("li",{parentName:"ul"},"App.tsx \u2013 main application component integrating Tldraw and multiplayer state.")),(0,n.kt)("h3",{id:"frontend-technologies"},"Frontend Technologies"),(0,n.kt)("p",null,"The frontend of the project is built using React and leverages various libraries and tools for enhanced functionality. Here is an overview of the key frontend technologies:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"React: A JavaScript library for building user interfaces."),(0,n.kt)("li",{parentName:"ul"},"Yjs: A real-time collaboration framework for synchronizing shared state."),(0,n.kt)("li",{parentName:"ul"},"Tldraw: A library for drawing functionalities in the application. We use the old version of tldraw: ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/tldraw/tldraw-v1"},"https://github.com/tldraw/tldraw-v1"),", after the tldraw team releases the official update of the new version, we will work on the new version and integrate it with the needs of our users. ")),(0,n.kt)("h3",{id:"state-managment"},"State Managment"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"Yjs is integrated into the project for real-time collaboration. The central state (shapes, bindings, assets) is managed using Yjs maps."),(0,n.kt)("li",{parentName:"ol"},"store.ts handles the configuration of Yjs, WebSocket connections, and provides centralized maps for shapes, bindings, and assets"),(0,n.kt)("li",{parentName:"ol"},"useMultiplayerState.ts -This hook manages the multiplayer state, including loading rooms, handling file system operations, and updating Yjs maps:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Mounting and handling changes in Tldraw App."),(0,n.kt)("li",{parentName:"ul"},"Presence management and user updates."),(0,n.kt)("li",{parentName:"ul"},"File system operations like opening and saving projects.")))),(0,n.kt)("h4",{id:"usetldrawuisanitizerts"},"useTldrawUiSanitizer.ts"),(0,n.kt)("p",null,"This hook is designed to observe changes in the DOM, specifically targeting certain buttons and a horizontal rule (< hr>), and hides them if they match a specific ID pattern. We hide this elements and left just only Language and Keyboard shortcuts."),(0,n.kt)("h4",{id:"event-handling"},"Event Handling"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"onMount: Handles mounting of the Tldraw app."),(0,n.kt)("li",{parentName:"ul"},"onChangePage: Manages page changes and updates Yjs maps."),(0,n.kt)("li",{parentName:"ul"},"onUndo and onRedo: Handle undo and redo operations."),(0,n.kt)("li",{parentName:"ul"},"onChangePresence: Manages presence changes in the collaborative environment."),(0,n.kt)("li",{parentName:"ul"},"onAssetCreate: This function is triggered when a user attempts to upload an asset (like an image or a file).")),(0,n.kt)("h4",{id:"useful-links"},"Useful links"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://tldraw.dev/"},"https://tldraw.dev/")," - documentation for the new version of tldraw")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://old.tldraw.com/"},"https://old.tldraw.com/")," - tldraw live application")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://github.com/tldraw/tldraw-v1"},"https://github.com/tldraw/tldraw-v1")," - tldraw v1 repo")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://github.com/MaxNoetzold/y-mongodb-provider"},"https://github.com/MaxNoetzold/y-mongodb-provider")," - code from this package was used to add mongodb as a persistence to tldraw")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://discord.com/invite/SBBEVCA4PG"},"https://discord.com/invite/SBBEVCA4PG")," discord channel with open questions and answers")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://grafana.dbildungscloud.dev/d/b6b28b2b-3129-4772-8102-e32981d2c2e3/devops-tldraw-metrics?orgId=1&refresh=1m&var-source=sc-dev-dbc&var-env=main&var-env=tldraw-debugging"},"https://grafana.dbildungscloud.dev/d/b6b28b2b-3129-4772-8102-e32981d2c2e3/devops-tldraw-metrics?orgId=1&refresh=1m&var-source=sc-dev-dbc&var-env=main&var-env=tldraw-debugging")," - grafana v")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://grafana.dbildungscloud.org/d/b6b28b2b-3129-4772-8102-e32981d2c2e0/devops-tldraw?orgId=1&from=now-6h&to=now&refresh=1m"},"https://grafana.dbildungscloud.org/d/b6b28b2b-3129-4772-8102-e32981d2c2e0/devops-tldraw?orgId=1&from=now-6h&to=now&refresh=1m")," - grafana metrics")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://github.com/nimeshnayaju/yjs-tldraw"},"https://github.com/nimeshnayaju/yjs-tldraw")," - yjs with tldraw POC")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://github.com/yjs/y-websocket/tree/master/bin"},"https://github.com/yjs/y-websocket/tree/master/bin")," - yjs/y-websocket repo")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://github.com/erdtool/yjs-scalable-ws-backend/tree/main"},"https://github.com/erdtool/yjs-scalable-ws-backend/tree/main")," - Yjs scalable WS backend with redis example")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://teamchat.dbildungscloud.de/channel/G9hJWv92zXEESKK3X"},"https://teamchat.dbildungscloud.de/channel/G9hJWv92zXEESKK3X"),' - rocketchat discussion "tldraw syncronisation for release again"')),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("a",{parentName:"p",href:"https://teamchat.dbildungscloud.de/group/SagK4sCyujhu6yZr8"},"https://teamchat.dbildungscloud.de/group/SagK4sCyujhu6yZr8"),' - rocketchat discussion "Tldraw deployment"s'))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f016df95.dd7ade05.js b/assets/js/f016df95.dd7ade05.js deleted file mode 100644 index 26e5dfa..0000000 --- a/assets/js/f016df95.dd7ade05.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[2857],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>w});var a=r(7294);function l(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function n(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function o(e){for(var t=1;t=0||(l[r]=e[r]);return l}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(l[r]=e[r])}return l}var s=a.createContext({}),c=function(e){var t=a.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var r=e.components,l=e.mdxType,n=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=c(r),m=l,w=p["".concat(s,".").concat(m)]||p[m]||d[m]||n;return r?a.createElement(w,o(o({ref:t},u),{},{components:r})):a.createElement(w,o({ref:t},u))}));function w(e,t){var r=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var n=r.length,o=new Array(n);o[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[p]="string"==typeof e?e:l,o[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>n,metadata:()=>i,toc:()=>c});var a=r(7462),l=(r(7294),r(3905));const n={},o="Local setup",i={unversionedId:"services/tldraw/Local setup",id:"services/tldraw/Local setup",title:"Local setup",description:"To run tldraw locally:",source:"@site/docs/services/tldraw/Local setup.md",sourceDirName:"services/tldraw",slug:"/services/tldraw/Local setup",permalink:"/docs/services/tldraw/Local setup",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/services/tldraw/Local setup.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"How it works",permalink:"/docs/services/tldraw/How it works"},next:{title:"Technical details",permalink:"/docs/services/tldraw/Technical details"}},s={},c=[{value:"To run tldraw locally:",id:"to-run-tldraw-locally",level:3},{value:"Create new whiteboard:",id:"create-new-whiteboard",level:3}],u={toc:c},p="wrapper";function d(e){let{components:t,...r}=e;return(0,l.kt)(p,(0,a.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"local-setup"},"Local setup"),(0,l.kt)("h3",{id:"to-run-tldraw-locally"},"To run tldraw locally:"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"Run redis i.e. in a docker container, it will work on localhost:6379 by default which is what the REDIS_URI env var is set to, for example on wsl: ",(0,l.kt)("a",{parentName:"li",href:"https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/"},"https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/")),(0,l.kt)("li",{parentName:"ol"},"Add to server repo the .env with following values\nPlease note redis default user is use and you can pass random value as password like the 123.")),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"REDIS_URI=redis://default:",(0,l.kt)("a",{parentName:"li",href:"mailto:123@127.0.0.1"},"123@127.0.0.1"),":6379"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_ADMIN_API_CLIENT__API_KEY=randomString"),(0,l.kt)("li",{parentName:"ul"},"ADMIN_API__ALLOWED_API_KEYS=randomString"),(0,l.kt)("li",{parentName:"ul"},"TLDRAW_ADMIN_API_CLIENT__BASE_URL=http://localhost:3349")),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"To run",(0,l.kt)("ol",{parentName:"li"},(0,l.kt)("li",{parentName:"ol"},"npm run nest:start:dev (schulcloud-server)"),(0,l.kt)("li",{parentName:"ol"},"npm run nest:start:files-storage:dev (schulcloud-server with s3, if you want to upload files)"),(0,l.kt)("li",{parentName:"ol"},"npm run nest:start:tldraw:dev (schulcloud-server)"),(0,l.kt)("li",{parentName:"ol"},"npm run dev (schulcloud-client)"),(0,l.kt)("li",{parentName:"ol"},"npm run servce (nuxt-client)"),(0,l.kt)("li",{parentName:"ol"},"npm run dev (tldraw-client)")))),(0,l.kt)("h3",{id:"create-new-whiteboard"},"Create new whiteboard:"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"Go to a course"),(0,l.kt)("li",{parentName:"ol"},"Go to 'Column board'"),(0,l.kt)("li",{parentName:"ol"},"Create a new card and a new 'Whiteboard' element within it, then click it"),(0,l.kt)("li",{parentName:"ol"},"A new browser tab with URL like: http://localhost:4000/tldraw?roomName=65c37329b2f97cc714d31c00 will open"),(0,l.kt)("li",{parentName:"ol"},"Change the port part from 4000 to 3046, which is the default port of tldraw-client app"),(0,l.kt)("li",{parentName:"ol"},"You should see a working tldraw whiteboard now")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f701fe34.c395d937.js b/assets/js/f701fe34.c395d937.js deleted file mode 100644 index a7ded6c..0000000 --- a/assets/js/f701fe34.c395d937.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[4020],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>f});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function l(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=r.createContext({}),d=function(e){var t=r.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},c=function(e){var t=d(e.components);return r.createElement(i.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},w=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,i=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=d(a),w=n,f=u["".concat(i,".").concat(w)]||u[w]||p[w]||o;return a?r.createElement(f,l(l({ref:t},c),{},{components:a})):r.createElement(f,l({ref:t},c))}));function f(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,l=new Array(o);l[0]=w;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s[u]="string"==typeof e?e:n,l[1]=s;for(var d=2;d{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>p,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var r=a(7462),n=(a(7294),a(3905));const o={},l="How it works",s={unversionedId:"services/tldraw/How it works",id:"services/tldraw/How it works",title:"How it works",description:"Configuration",source:"@site/docs/services/tldraw/How it works.md",sourceDirName:"services/tldraw",slug:"/services/tldraw/How it works",permalink:"/docs/services/tldraw/How it works",draft:!1,editUrl:"https://github.com/hpi-schul-cloud/hpi-schul-cloud.github.io/blob/main/docs/services/tldraw/How it works.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Local Setup",permalink:"/docs/services/etherpad/Local setup"},next:{title:"Local setup",permalink:"/docs/services/tldraw/Local setup"}},i={},d=[{value:"Configuration",id:"configuration",level:2},{value:"Create",id:"create",level:2},{value:"Usage",id:"usage",level:2},{value:"Connection",id:"connection",level:3},{value:"Sending updates/storing data",id:"sending-updatesstoring-data",level:3},{value:"Delete",id:"delete",level:2},{value:"Assets",id:"assets",level:2},{value:"files upload",id:"files-upload",level:3},{value:"files deletion",id:"files-deletion",level:3}],c={toc:d},u="wrapper";function p(e){let{components:t,...a}=e;return(0,n.kt)(u,(0,r.Z)({},c,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"how-it-works"},"How it works"),(0,n.kt)("h2",{id:"configuration"},"Configuration"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"NEST_LOG_LEVEL - logging level"),(0,n.kt)("li",{parentName:"ul"},"FEATURE_TLDRAW_ENABLED - flag determining if tldraw is enabled"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_URI - address of tldraw server "),(0,n.kt)("li",{parentName:"ul"},"INCOMING_REQUEST_TIMEOUT - request timeout"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_DB_URL - mongoDB connection string"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__SOCKET_PORT - port number for websockets connection"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__PING_TIMEOUT - timeout for ping-pong during establishing websockets connection"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__FINALIZE_DELAY - delay in ms before checking if can finalize a tldraw board"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__GC_ENABLED - if tldraw garbage collector should be enabled"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__DB_COMPRESS_THRESHOLD - threshold size for tldraw mongo documents compression"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__MAX_DOCUMENT_SIZE - max size of a single tldraw document in mongo"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__ASSETS_ENABLED - enables uploading assets to tldraw board"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__ASSETS_SYNC_ENABLED - enables synch of tldraw board assets with filestorage (no longer used)"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__ASSETS_MAX_SIZE - maximum asset size in bytes"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW__ASSETS_ALLOWED_MIME_TYPES_LIST - listy of allowed assets MIME types"),(0,n.kt)("li",{parentName:"ul"},"REDIS_URI - Redis connection string"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_CLIENT_REPLICAS - number of pods for tldraw-client "),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_SERVER_REPLICAS - number of pods for tldraw-server"),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_ADMIN_API_CLIENT__API_KEY - authorization API key for accessing tldraw controller (delete flow) "),(0,n.kt)("li",{parentName:"ul"},"TLDRAW_ADMIN_API_CLIENT__BASE_URL - address of tldraw controller (delete flow) ")),(0,n.kt)("p",null,"In order to have deletion functionality fully working you have to fill those feature flags, e.g.:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"ADMIN_API__ALLOWED_API_KEYS=",'["7ccd4e11-c6f6-48b0-81eb-abcdef123456"]'),(0,n.kt)("li",{parentName:"ul"},'TLDRAW_ADMIN_API_CLIENT__API_KEY="7ccd4e11-c6f6-48b0-81eb-abcdef123456"'),(0,n.kt)("li",{parentName:"ul"},'TLDRAW_ADMIN_API_CLIENT__BASE_URL="http://localhost:3349"')),(0,n.kt)("h2",{id:"create"},"Create"),(0,n.kt)("p",null,"![Create tldraw workflow]","(./assets/Create TLDRAW.drawio.svg)"),(0,n.kt)("p",null,"Creation of Tldraw starts with creation proccess for Courses and CourseBoard. It has Representation in CourseBoard as card's element (BoardNode in db). After creating Representation of drawing we can enter actual tldraw SPA client (left side of picture)."),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"User enters CourseBoard and creates Representation of whiteboard (tldraw) in CourseCard."),(0,n.kt)("li",{parentName:"ol"},"Data is saved and feedback with proper creation is given - user can see Representation and can enter whiteboard."),(0,n.kt)("li",{parentName:"ol"},"By entering whiteboard user is redirected to SPA tldraw-client."),(0,n.kt)("li",{parentName:"ol"},"Tldraw-client is starting WS connection with tldraw-server."),(0,n.kt)("li",{parentName:"ol"},"Tldraw-server firstly checks if user has permission to this resource (by checking if user has a permission to Representation of whiteboard -BoardNode).\nId of Representation is same as drawingName, which is visible in tldraw-client url."),(0,n.kt)("li",{parentName:"ol"},"If user has permission tldraw-server is allowing to remain connection and getting drawing data from separate tldraw-db. If there were no drawing data saved tldraw-server will create it automatically. ")),(0,n.kt)("h2",{id:"usage"},"Usage"),(0,n.kt)("p",null,"![Usage tldraw workflow]","(./assets/Use tldraw.drawio.svg)"),(0,n.kt)("h3",{id:"connection"},"Connection"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"user joins tldraw board"),(0,n.kt)("li",{parentName:"ol"},"tldraw-client connects to one of the tldraw-server pods and tries to establish websocket connection"),(0,n.kt)("li",{parentName:"ol"},"tldraw-server calls schulcloud-server via HTTP requests to check user permissions, if everything is fine the websocket connection is established"),(0,n.kt)("li",{parentName:"ol"},"tldraw-server gets stored tldraw board data from mongodb and sends it via websocket to connected users"),(0,n.kt)("li",{parentName:"ol"},"tldraw-server starts subscribing to Redis PUBSUB channel corresponding to tldraw board name to listen to changes from other pods")),(0,n.kt)("h3",{id:"sending-updatesstoring-data"},"Sending updates/storing data"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"tldraw-client sends user's drawing changes to the tldraw-server via websocket connection"),(0,n.kt)("li",{parentName:"ol"},"tldraw-server stores the board update in the mongodb - basically creates a diff between what's already stored and what's being updated"),(0,n.kt)("li",{parentName:"ol"},"tldraw-server pushes the update to correct Redis channel so that clients connected to different pods have synchronized board data"),(0,n.kt)("li",{parentName:"ol"},"other pods subscribing to Redis channel send updates to their connected clients via websocket whenever they see a new message on Redis channel")),(0,n.kt)("h2",{id:"delete"},"Delete"),(0,n.kt)("p",null,"![Delete tldraw workflow]","(./assets/Delete TLDRAW.drawio.svg)"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"User from schulcloud app in CourseBoard deletes whiteboard (tldraw) instance form CardBoard."),(0,n.kt)("li",{parentName:"ol"},"Having drawingName sc-server is removing Representation data in sc-database - BoardNodes collection ( drawingName === BoardNode id)"),(0,n.kt)("li",{parentName:"ol"},"Sc-server is calling tldraw-server via tldraw-management rules in tldraw-server-svc to delete all data that has given id)."),(0,n.kt)("li",{parentName:"ol"},"After deletion user sees refreshed state of CourseBoard. ")),(0,n.kt)("h2",{id:"assets"},"Assets"),(0,n.kt)("h3",{id:"files-upload"},"files upload"),(0,n.kt)("p",null,"Images/GIFs can be uploaded into tldraw whiteboard by every user with access to the board. We use s3 storage to physically store uploaded assets while tldraw only holds URL to a resource."),(0,n.kt)("p",null,"The files are uploaded by calling schulcloud-api's fileController upload endpoint. This is possible because tldraw is represented as a boardnode called drawing-element. Mongo id of this drawing-element is a roomId used in URL param when connecting to a specific board."),(0,n.kt)("h3",{id:"files-deletion"},"files deletion"),(0,n.kt)("p",null,"Because of the undo/redo functionality of tldraw (user can basically undo an upload of an image, undo a deletion, then redo upload etc.) we needed a way to clean up unused assets from the storage. We could not use soft delete/restore endpoints every time undo/redo happens due to various issues with performance/user experience and technical challenges that arose when testing different scenarios. We decided to go with cron job solution: once per day, at midnight by default, we would go through each board stored in database, get every asset that's stored as URL but no longer used as an active drawing and then delete all of them via amqp call to filesStorage service."),(0,n.kt)("p",null,"For implementation details, take a look at: tldraw-files.console.ts."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/main.7c86c014.js b/assets/js/main.7c86c014.js new file mode 100644 index 0000000..b552c7e --- /dev/null +++ b/assets/js/main.7c86c014.js @@ -0,0 +1,2 @@ +/*! For license information please see main.7c86c014.js.LICENSE.txt */ +(self.webpackChunkdataport_docusaurus=self.webpackChunkdataport_docusaurus||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),o=n(7462),a=n(8356),i=n.n(a),l=n(6887);const s={"0579a3a5":[()=>n.e(5014).then(n.bind(n,7532)),"@site/docs/tldraw-server/How it works.md",7532],"09271db2":[()=>n.e(1670).then(n.t.bind(n,5745,19)),"/home/runner/work/schulcloud-documentation/schulcloud-documentation/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",5745],"09e11c27":[()=>n.e(1932).then(n.bind(n,5170)),"@site/docs/nuxt-client/9_HintsForWorking.md",5170],"0e384e19":[()=>n.e(9671).then(n.bind(n,9881)),"@site/docs/intro.md",9881],"14307e05":[()=>n.e(2024).then(n.bind(n,3412)),"@site/docs/syncronizations/TSP/Architecture.md",3412],"14eb3368":[()=>Promise.all([n.e(532),n.e(9817)]).then(n.bind(n,4228)),"@theme/DocCategoryGeneratedIndexPage",4228],17896441:[()=>Promise.all([n.e(532),n.e(2784),n.e(7918)]).then(n.bind(n,230)),"@theme/DocItem",230],"18a636a5":[()=>n.e(5556).then(n.bind(n,6807)),"@site/docs/nuxt-client/3_GitConventions.md",6807],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,2027)),"@theme/SearchPage",2027],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c700299":[()=>n.e(7464).then(n.bind(n,9760)),"@site/docs/schulcloud-server/Coding-Guidelines/repositories.md",9760],"1df93b7f":[()=>Promise.all([n.e(532),n.e(3237)]).then(n.bind(n,3808)),"@site/src/pages/index.tsx",3808],"1e32a951":[()=>n.e(4832).then(n.bind(n,9754)),"@site/docs/e2e-system-tests/3_Tags.md",9754],"1f391b9e":[()=>Promise.all([n.e(532),n.e(2784),n.e(3085)]).then(n.bind(n,4247)),"@theme/MDXPage",4247],"2276cd77":[()=>n.e(5125).then(n.t.bind(n,9973,19)),"~docs/default/category-docs-tutorialsidebar-category-how-to-update-the-docs-da9.json",9973],"234d9ac0":[()=>n.e(8844).then(n.bind(n,8545)),"@site/docs/schulcloud-server/Development/vs-code.md",8545],"25d29d9b":[()=>n.e(3195).then(n.bind(n,9368)),"@site/docs/schulcloud-server/Coding-Guidelines/controllers.md",9368],"287ec6bc":[()=>n.e(4615).then(n.bind(n,6573)),"@site/docs/nuxt-client/1_ProjectStructure.md",6573],"306c3845":[()=>n.e(6616).then(n.t.bind(n,2776,19)),"/home/runner/work/schulcloud-documentation/schulcloud-documentation/.docusaurus/@easyops-cn/docusaurus-search-local/default/plugin-route-context-module-100.json",2776],"393be207":[()=>n.e(7414).then(n.bind(n,3123)),"@site/src/pages/markdown-page.md",3123],"4648a6e8":[()=>n.e(3879).then(n.bind(n,5208)),"@site/docs/schulcloud-server/Development/rocket-chat.md",5208],"46dbb8ab":[()=>n.e(1594).then(n.bind(n,3730)),"@site/docs/Informations/detect-dependency-cycles.md",3730],48751006:[()=>n.e(7858).then(n.bind(n,7660)),"@site/docs/schulcloud-server/Coding-Guidelines/exception-handling.md",7660],"4ad69fc2":[()=>n.e(5773).then(n.bind(n,7489)),"@site/docs/schulcloud-server/Migrations.md",7489],"4f93518d":[()=>n.e(8404).then(n.bind(n,3124)),"@site/docs/schulcloud-server/Coding-Guidelines/access-legacy-code.md",3124],"579213b9":[()=>n.e(3093).then(n.bind(n,9405)),"@site/docs/How to update the docs/congratulations.md",9405],"5bde3a12":[()=>n.e(4211).then(n.bind(n,2779)),"@site/docs/services/etherpad/Local setup.md",2779],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,6809)),"@generated/docusaurus.config",6809],"64027feb":[()=>n.e(7816).then(n.bind(n,3144)),"@site/docs/schulcloud-server/architecture.md",3144],"679fb4ac":[()=>n.e(1796).then(n.bind(n,5470)),"@site/docs/schulcloud-server/Coding-Guidelines/code-style.md",5470],"67d0f22c":[()=>n.e(6947).then(n.bind(n,2226)),"@site/docs/schulcloud-server/Coding-Guidelines/logging.md",2226],"6af581cf":[()=>n.e(8639).then(n.bind(n,5064)),"@site/docs/nuxt-client/0_GettingStarted.md",5064],"74c4112b":[()=>n.e(6190).then(n.bind(n,5806)),"@site/docs/tldraw-server/Local setup.md",5806],76533127:[()=>n.e(9903).then(n.bind(n,9541)),"@site/docs/schulcloud-client/Getting started.md",9541],"76ac0d9b":[()=>n.e(4038).then(n.bind(n,3406)),"@site/docs/schulcloud-server/Getting started.md",3406],"785f7b5a":[()=>n.e(8981).then(n.bind(n,9846)),"@site/docs/nuxt-client/5_WritingTests.md",9846],"78e80160":[()=>n.e(7975).then(n.bind(n,8794)),"@site/docs/nuxt-client/8_IdentifyingAndResolvingCircularDependencies.md",8794],"7fbcedce":[()=>n.e(9539).then(n.bind(n,2398)),"@site/docs/nuxt-client/7_Colors.md",2398],"7fbd2616":[()=>n.e(5896).then(n.bind(n,8411)),"@site/docs/schulcloud-server/Development/git.md",8411],81589697:[()=>n.e(2996).then(n.bind(n,354)),"@site/docs/How to update the docs/deploy-your-site.md",354],"85a91618":[()=>n.e(2462).then(n.bind(n,796)),"@site/docs/schulcloud-server/our nextjs modules/room-member-module/index.md",796],"88fdfd2d":[()=>n.e(2732).then(n.bind(n,7947)),"@site/docs/How to update the docs/markdown-features.mdx",7947],"8b2430e2":[()=>n.e(6012).then(n.bind(n,6888)),"@site/docs/e2e-system-tests/0_GettingStarted.md",6888],"8e3ce21d":[()=>n.e(4233).then(n.bind(n,6358)),"@site/docs/schulcloud-server/Coding-Guidelines/event-handling.md",6358],"8e9e9291":[()=>n.e(4968).then(n.bind(n,4635)),"@site/docs/How to update the docs/create-a-blog-post.md",4635],"8fc771c1":[()=>n.e(8896).then(n.bind(n,34)),"@site/docs/schulcloud-server/Development/keycloak.md",34],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"95fe1a58":[()=>n.e(9739).then(n.t.bind(n,3769,19)),"/home/runner/work/schulcloud-documentation/schulcloud-documentation/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"9a9bfca7":[()=>n.e(2341).then(n.bind(n,1040)),"@site/docs/schulcloud-server/Coding-Guidelines/micro-orm.md",1040],"9bc4dd96":[()=>n.e(770).then(n.t.bind(n,4832,19)),"~docs/default/category-docs-tutorialsidebar-category-nuxt-client-514.json",4832],"9e1b0827":[()=>n.e(2364).then(n.bind(n,2816)),"@site/docs/nuxt-client/2_CodeConventions.md",2816],a5f57a66:[()=>n.e(7022).then(n.bind(n,7655)),"@site/docs/nuxt-client/4_HowTo.md",7655],a6e79240:[()=>n.e(6074).then(n.bind(n,9480)),"@site/docs/syncronizations/TSP/How it works.md",9480],aa3d8eef:[()=>n.e(3941).then(n.t.bind(n,432,19)),"~docs/default/category-docs-tutorialsidebar-category-schulcloud-server-2d3.json",432],b6ce3ed6:[()=>n.e(4392).then(n.bind(n,748)),"@site/docs/e2e-system-tests/2_CodeConventions.md",748],b7891a86:[()=>n.e(1142).then(n.bind(n,2518)),"@site/docs/nuxt-client/ComponentGuidelines.md",2518],cc565af5:[()=>n.e(1292).then(n.bind(n,1938)),"@site/docs/schulcloud-server/Coding-Guidelines/deprection-workflow.md",1938],ce3b758c:[()=>n.e(6333).then(n.bind(n,1228)),"@site/docs/schulcloud-server/Coding-Guidelines/configuration.md",1228],d5e448b9:[()=>n.e(6584).then(n.t.bind(n,1041,19)),"~docs/default/category-docs-tutorialsidebar-category-e-2-e-system-tests-3ef.json",1041],d757ab52:[()=>n.e(9826).then(n.bind(n,3600)),"@site/docs/services/etherpad/How it works.md",3600],d8db4531:[()=>n.e(6207).then(n.bind(n,2474)),"@site/docs/e2e-system-tests/1_ProjectStructure.md",2474],dc9c4dc5:[()=>n.e(2395).then(n.bind(n,6390)),"@site/docs/How to update the docs/create-a-page.md",6390],dcaf9ebd:[()=>n.e(3589).then(n.bind(n,4532)),"@site/docs/schulcloud-server/Api.md",4532],dd56d1b0:[()=>n.e(3958).then(n.bind(n,5185)),"@site/docs/nuxt-client/6_Accessibility.md",5185],e4a1fa55:[()=>n.e(4293).then(n.bind(n,9567)),"@site/docs/schulcloud-server/Coding-Guidelines/testing.md",9567],e68d14cf:[()=>n.e(604).then(n.bind(n,4731)),"@site/docs/tldraw-server/Technical details.md",4731],e849eca6:[()=>n.e(8171).then(n.bind(n,3091)),"@site/docs/schulcloud-server/Coding-Guidelines/domain-object-validation.md",3091],e8e7469b:[()=>n.e(3027).then(n.t.bind(n,2407,19)),"~docs/default/category-docs-tutorialsidebar-category-schulcloud-client-f67.json",2407],f70b05ae:[()=>n.e(1779).then(n.bind(n,1539)),"@site/docs/How to update the docs/create-a-document.md",1539],ff57262e:[()=>n.e(8247).then(n.bind(n,3792)),"@site/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md",3792]};function u(e){let{error:t,retry:n,pastDelay:o}=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"))):o?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 p(e,t){if("*"===e)return i()({loading:u,loader:()=>n.e(4972).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 a=l[`${e}-${t}`],p={},f=[],h=[],m=(0,c.Z)(a);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=s[n];r&&(p[t]=r[0],f.push(r[1]),h.push(r[2]))})),i().Map({loading:u,loader:p,modules:f,webpack:()=>h,render(t,n){const i=JSON.parse(JSON.stringify(a));Object.entries(t).forEach((t=>{let[n,r]=t;const o=r.default;if(!o)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 o&&"function"!=typeof o||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{o[e]=r[e]}));let a=i;const l=n.split(".");l.slice(0,-1).forEach((e=>{a=a[e]})),a[l[l.length-1]]=o}));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,o.Z)({},i,n)))}})}const f=[{path:"/markdown-page",component:p("/markdown-page","4c1"),exact:!0},{path:"/search",component:p("/search","407"),exact:!0},{path:"/docs",component:p("/docs","720"),routes:[{path:"/docs/category/e2e-system-tests",component:p("/docs/category/e2e-system-tests","62d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/category/how-to-update-the-docs",component:p("/docs/category/how-to-update-the-docs","092"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/category/nuxt-client",component:p("/docs/category/nuxt-client","e2a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/category/schulcloud-client",component:p("/docs/category/schulcloud-client","ebf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/category/schulcloud-server",component:p("/docs/category/schulcloud-server","fad"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/e2e-system-tests/CodeConventions",component:p("/docs/e2e-system-tests/CodeConventions","ec0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/e2e-system-tests/GettingStarted",component:p("/docs/e2e-system-tests/GettingStarted","2c8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/e2e-system-tests/ProjectStructure",component:p("/docs/e2e-system-tests/ProjectStructure","63d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/e2e-system-tests/Tags",component:p("/docs/e2e-system-tests/Tags","fa0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/congratulations",component:p("/docs/How to update the docs/congratulations","b44"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/create-a-blog-post",component:p("/docs/How to update the docs/create-a-blog-post","ef7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/create-a-document",component:p("/docs/How to update the docs/create-a-document","30e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/create-a-page",component:p("/docs/How to update the docs/create-a-page","bda"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/deploy-your-site",component:p("/docs/How to update the docs/deploy-your-site","2c7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/How to update the docs/markdown-features",component:p("/docs/How to update the docs/markdown-features","608"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/Informations/detect-dependency-cycles",component:p("/docs/Informations/detect-dependency-cycles","277"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/intro",component:p("/docs/intro","aed"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/Accessibility",component:p("/docs/nuxt-client/Accessibility","379"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/CodeConventions",component:p("/docs/nuxt-client/CodeConventions","902"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/Colors",component:p("/docs/nuxt-client/Colors","389"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/ComponentGuidelines",component:p("/docs/nuxt-client/ComponentGuidelines","005"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/GettingStarted",component:p("/docs/nuxt-client/GettingStarted","17a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/GitConventions",component:p("/docs/nuxt-client/GitConventions","3c7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/HintsForWorking",component:p("/docs/nuxt-client/HintsForWorking","833"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/HowTo",component:p("/docs/nuxt-client/HowTo","d3d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/IdentifyingAndResolvingCircularDependencies",component:p("/docs/nuxt-client/IdentifyingAndResolvingCircularDependencies","166"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/ProjectStructure",component:p("/docs/nuxt-client/ProjectStructure","f6c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nuxt-client/WritingTests",component:p("/docs/nuxt-client/WritingTests","640"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-client/Getting started",component:p("/docs/schulcloud-client/Getting started","464"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Api",component:p("/docs/schulcloud-server/Api","ff8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/architecture",component:p("/docs/schulcloud-server/architecture","67a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/access-legacy-code",component:p("/docs/schulcloud-server/Coding-Guidelines/access-legacy-code","7ca"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/code-style",component:p("/docs/schulcloud-server/Coding-Guidelines/code-style","b84"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/configuration",component:p("/docs/schulcloud-server/Coding-Guidelines/configuration","a2f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/controllers",component:p("/docs/schulcloud-server/Coding-Guidelines/controllers","d09"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/deprection-workflow",component:p("/docs/schulcloud-server/Coding-Guidelines/deprection-workflow","d71"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/domain-object-validation",component:p("/docs/schulcloud-server/Coding-Guidelines/domain-object-validation","daf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/event-handling",component:p("/docs/schulcloud-server/Coding-Guidelines/event-handling","5ce"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/exception-handling",component:p("/docs/schulcloud-server/Coding-Guidelines/exception-handling","e0d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/logging",component:p("/docs/schulcloud-server/Coding-Guidelines/logging","c7c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/micro-orm",component:p("/docs/schulcloud-server/Coding-Guidelines/micro-orm","8cf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/modules-submodules",component:p("/docs/schulcloud-server/Coding-Guidelines/modules-submodules","733"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/repositories",component:p("/docs/schulcloud-server/Coding-Guidelines/repositories","10d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Coding-Guidelines/testing",component:p("/docs/schulcloud-server/Coding-Guidelines/testing","8a7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Development/git",component:p("/docs/schulcloud-server/Development/git","e08"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Development/keycloak",component:p("/docs/schulcloud-server/Development/keycloak","a56"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Development/rocket-chat",component:p("/docs/schulcloud-server/Development/rocket-chat","311"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Development/vs-code",component:p("/docs/schulcloud-server/Development/vs-code","e39"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Getting started",component:p("/docs/schulcloud-server/Getting started","081"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/Migrations",component:p("/docs/schulcloud-server/Migrations","9ef"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/schulcloud-server/our nextjs modules/room-member-module",component:p("/docs/schulcloud-server/our nextjs modules/room-member-module","fdd"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/services/etherpad/How it works",component:p("/docs/services/etherpad/How it works","f9a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/services/etherpad/Local setup",component:p("/docs/services/etherpad/Local setup","2d0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/syncronizations/TSP/Architecture",component:p("/docs/syncronizations/TSP/Architecture","971"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/syncronizations/TSP/How it works",component:p("/docs/syncronizations/TSP/How it works","de8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/tldraw-server/How it works",component:p("/docs/tldraw-server/How it works","f18"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/tldraw-server/Local setup",component:p("/docs/tldraw-server/Local setup","81b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/tldraw-server/Technical details",component:p("/docs/tldraw-server/Technical details","85a"),exact:!0,sidebar:"tutorialSidebar"}]},{path:"/",component:p("/","dc7"),exact:!0},{path:"*",component:p("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,t:()=>a});var r=n(7294);const o=r.createContext(!1);function a(e){let{children:t}=e;const[n,a]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{a(!0)}),[]),r.createElement(o.Provider,{value:n},t)}},7221:(e,t,n)=>{"use strict";var r=n(7294),o=n(3935),a=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 p(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var f=n(7462),h=n(5742),m=n(2263),g=n(4996),v=n(6668),b=n(1944),y=n(4711),w=n(9727),k=n(3320),E=n(8780),S=n(197);function x(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,m.Z)(),n=(0,y.l)();return r.createElement(h.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:o}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:o})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function C(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.Z)(),o=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,m.Z)(),{pathname:r}=(0,c.TH)();return e+(0,E.applyTrailingSlash)((0,g.Z)(r),{trailingSlash:n,baseUrl:t})}(),a=t?`${n}${t}`:o;return r.createElement(h.Z,null,r.createElement("meta",{property:"og:url",content:a}),r.createElement("link",{rel:"canonical",href:a}))}function _(){const{i18n:{currentLocale:e}}=(0,m.Z)(),{metadata:t,image:n}=(0,v.L)();return r.createElement(r.Fragment,null,r.createElement(h.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(b.d,{image:n}),r.createElement(C,null),r.createElement(x,null),r.createElement(S.Z,{tag:k.HX,locale:e}),r.createElement(h.Z,null,t.map(((e,t)=>r.createElement("meta",(0,f.Z)({key:t},e))))))}const T=new Map;function L(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.f)(u.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),P=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()=>o.forEach((e=>e?.()))}const O=function(e){let{children:t,location:n,previousLocation:o}=e;return(0,r.useLayoutEffect)((()=>{o!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)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:o}),R("onRouteDidUpdate",{previousLocation:o,location:n}))}),[o,n]),t};function N(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 I extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),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}),N(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(O,{previousLocation:this.previousLocation,location:t},r.createElement(c.AW,{location:t,render:()=>e}))}}const D=I,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",j="__docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function z(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('${M}');\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(h.Z,null,r.createElement("script",null,z(e))),r.createElement("div",{id:M}))}function G(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,m.Z)(),{pathname:n}=(0,c.TH)();return t&&n===e?r.createElement($,null):null}function U(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:o,localeConfigs:a}}=(0,m.Z)(),i=(0,g.Z)(e),{htmlLang:l,direction:s}=a[o];return r.createElement(h.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 H=n(4763),q=n(2389);function Q(){const e=(0,q.Z)();return r.createElement(h.Z,null,r.createElement("html",{"data-has-hydrated":e}))}function Z(){const e=(0,d.H)(u.Z),t=(0,c.TH)();return r.createElement(H.Z,null,r.createElement(P.M,null,r.createElement(A.t,null,r.createElement(p,null,r.createElement(U,null),r.createElement(_,null),r.createElement(G,null),r.createElement(D,{location:L(t)},e)),r.createElement(Q,null))))}var V=n(6887);const W=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 o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.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 K=n(9670);const Y=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Y.has(e))(e))return!1;Y.add(e);const t=(0,d.f)(u.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(V).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?W(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),N(e))},te=Object.freeze(ee);if(l.Z.canUseDOM){window.docusaurus=te;const e=o.hydrate;N(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(a.VK,null,r.createElement(Z,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>c,M:()=>d});var r=n(7294),o=n(6809);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"intro","docs":[{"id":"e2e-system-tests/CodeConventions","path":"/docs/e2e-system-tests/CodeConventions","sidebar":"tutorialSidebar"},{"id":"e2e-system-tests/GettingStarted","path":"/docs/e2e-system-tests/GettingStarted","sidebar":"tutorialSidebar"},{"id":"e2e-system-tests/ProjectStructure","path":"/docs/e2e-system-tests/ProjectStructure","sidebar":"tutorialSidebar"},{"id":"e2e-system-tests/Tags","path":"/docs/e2e-system-tests/Tags","sidebar":"tutorialSidebar"},{"id":"How to update the docs/congratulations","path":"/docs/How to update the docs/congratulations","sidebar":"tutorialSidebar"},{"id":"How to update the docs/create-a-blog-post","path":"/docs/How to update the docs/create-a-blog-post","sidebar":"tutorialSidebar"},{"id":"How to update the docs/create-a-document","path":"/docs/How to update the docs/create-a-document","sidebar":"tutorialSidebar"},{"id":"How to update the docs/create-a-page","path":"/docs/How to update the docs/create-a-page","sidebar":"tutorialSidebar"},{"id":"How to update the docs/deploy-your-site","path":"/docs/How to update the docs/deploy-your-site","sidebar":"tutorialSidebar"},{"id":"How to update the docs/markdown-features","path":"/docs/How to update the docs/markdown-features","sidebar":"tutorialSidebar"},{"id":"Informations/detect-dependency-cycles","path":"/docs/Informations/detect-dependency-cycles","sidebar":"tutorialSidebar"},{"id":"intro","path":"/docs/intro","sidebar":"tutorialSidebar"},{"id":"nuxt-client/Accessibility","path":"/docs/nuxt-client/Accessibility","sidebar":"tutorialSidebar"},{"id":"nuxt-client/CodeConventions","path":"/docs/nuxt-client/CodeConventions","sidebar":"tutorialSidebar"},{"id":"nuxt-client/Colors","path":"/docs/nuxt-client/Colors","sidebar":"tutorialSidebar"},{"id":"nuxt-client/ComponentGuidelines","path":"/docs/nuxt-client/ComponentGuidelines","sidebar":"tutorialSidebar"},{"id":"nuxt-client/GettingStarted","path":"/docs/nuxt-client/GettingStarted","sidebar":"tutorialSidebar"},{"id":"nuxt-client/GitConventions","path":"/docs/nuxt-client/GitConventions","sidebar":"tutorialSidebar"},{"id":"nuxt-client/HintsForWorking","path":"/docs/nuxt-client/HintsForWorking","sidebar":"tutorialSidebar"},{"id":"nuxt-client/HowTo","path":"/docs/nuxt-client/HowTo","sidebar":"tutorialSidebar"},{"id":"nuxt-client/IdentifyingAndResolvingCircularDependencies","path":"/docs/nuxt-client/IdentifyingAndResolvingCircularDependencies","sidebar":"tutorialSidebar"},{"id":"nuxt-client/ProjectStructure","path":"/docs/nuxt-client/ProjectStructure","sidebar":"tutorialSidebar"},{"id":"nuxt-client/WritingTests","path":"/docs/nuxt-client/WritingTests","sidebar":"tutorialSidebar"},{"id":"schulcloud-client/Getting started","path":"/docs/schulcloud-client/Getting started","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Api","path":"/docs/schulcloud-server/Api","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/architecture","path":"/docs/schulcloud-server/architecture","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/access-legacy-code","path":"/docs/schulcloud-server/Coding-Guidelines/access-legacy-code","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/code-style","path":"/docs/schulcloud-server/Coding-Guidelines/code-style","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/configuration","path":"/docs/schulcloud-server/Coding-Guidelines/configuration","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/controllers","path":"/docs/schulcloud-server/Coding-Guidelines/controllers","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/deprection-workflow","path":"/docs/schulcloud-server/Coding-Guidelines/deprection-workflow","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/domain-object-validation","path":"/docs/schulcloud-server/Coding-Guidelines/domain-object-validation","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/event-handling","path":"/docs/schulcloud-server/Coding-Guidelines/event-handling","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/exception-handling","path":"/docs/schulcloud-server/Coding-Guidelines/exception-handling","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/logging","path":"/docs/schulcloud-server/Coding-Guidelines/logging","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/micro-orm","path":"/docs/schulcloud-server/Coding-Guidelines/micro-orm","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/modules-submodules","path":"/docs/schulcloud-server/Coding-Guidelines/modules-submodules","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/repositories","path":"/docs/schulcloud-server/Coding-Guidelines/repositories","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Coding-Guidelines/testing","path":"/docs/schulcloud-server/Coding-Guidelines/testing","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Development/git","path":"/docs/schulcloud-server/Development/git","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Development/keycloak","path":"/docs/schulcloud-server/Development/keycloak","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Development/rocket-chat","path":"/docs/schulcloud-server/Development/rocket-chat","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Development/vs-code","path":"/docs/schulcloud-server/Development/vs-code","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Getting started","path":"/docs/schulcloud-server/Getting started","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/Migrations","path":"/docs/schulcloud-server/Migrations","sidebar":"tutorialSidebar"},{"id":"schulcloud-server/our nextjs modules/room-member-module/index","path":"/docs/schulcloud-server/our nextjs modules/room-member-module/","sidebar":"tutorialSidebar"},{"id":"services/etherpad/How it works","path":"/docs/services/etherpad/How it works","sidebar":"tutorialSidebar"},{"id":"services/etherpad/Local setup","path":"/docs/services/etherpad/Local setup","sidebar":"tutorialSidebar"},{"id":"syncronizations/TSP/Architecture","path":"/docs/syncronizations/TSP/Architecture","sidebar":"tutorialSidebar"},{"id":"syncronizations/TSP/How it works","path":"/docs/syncronizations/TSP/How it works","sidebar":"tutorialSidebar"},{"id":"tldraw-server/How it works","path":"/docs/tldraw-server/How it works","sidebar":"tutorialSidebar"},{"id":"tldraw-server/Local setup","path":"/docs/tldraw-server/Local setup","sidebar":"tutorialSidebar"},{"id":"tldraw-server/Technical details","path":"/docs/tldraw-server/Technical details","sidebar":"tutorialSidebar"},{"id":"/category/nuxt-client","path":"/docs/category/nuxt-client","sidebar":"tutorialSidebar"},{"id":"/category/schulcloud-client","path":"/docs/category/schulcloud-client","sidebar":"tutorialSidebar"},{"id":"/category/schulcloud-server","path":"/docs/category/schulcloud-server","sidebar":"tutorialSidebar"},{"id":"/category/e2e-system-tests","path":"/docs/category/e2e-system-tests","sidebar":"tutorialSidebar"},{"id":"/category/how-to-update-the-docs","path":"/docs/category/how-to-update-the-docs","sidebar":"tutorialSidebar"}],"draftIds":[],"sidebars":{"tutorialSidebar":{"link":{"path":"/docs/intro","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.4.3","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.3"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.4.3"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.4.3"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.3"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.3"},"@easyops-cn/docusaurus-search-local":{"type":"package","name":"@easyops-cn/docusaurus-search-local","version":"0.35.0"},"docusaurus-theme-mermaid":{"type":"package","name":"@docusaurus/theme-mermaid","version":"2.4.3"}}}'),u={siteConfig:o.default,siteMetadata:s,globalData:a,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:()=>p});var r=n(7294),o=n(412),a=n(5742),i=n(8780),l=n(179);function s(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},r.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),r.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),r.createElement(u,{error:t}))}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function c(e){let{error:t,tryAgain:n}=e;return r.createElement(p,{fallback:()=>r.createElement(s,{error:t,tryAgain:n})},r.createElement(a.Z,null,r.createElement("title",null,"Page Error")),r.createElement(l.Z,null,r.createElement(s,{error:t,tryAgain:n})))}const d=e=>r.createElement(c,e);class p extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.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??d)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={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:()=>a});var r=n(7294),o=n(405);function a(e){return r.createElement(o.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7462),o=n(7294),a=n(3727),i=n(8780),l=n(2263),s=n(3919),u=n(412);const c=o.createContext({collectLink:()=>{}});var d=n(4996);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:h,isActive:m,"data-noBrokenLinkCheck":g,autoAddBaseUrl:v=!0,...b}=e;const{siteConfig:{trailingSlash:y,baseUrl:w}}=(0,l.Z)(),{withBaseUrl:k}=(0,d.C)(),E=(0,o.useContext)(c),S=(0,o.useRef)(null);(0,o.useImperativeHandle)(t,(()=>S.current));const x=p||f;const C=(0,s.Z)(x),_=x?.replace("pathname://","");let T=void 0!==_?(L=_,v&&(e=>e.startsWith("/"))(L)?k(L):L):void 0;var L;T&&C&&(T=(0,i.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:w}));const A=(0,o.useRef)(!1),P=n?a.OL:a.rU,R=u.Z.canUseIntersectionObserver,O=(0,o.useRef)(),N=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,o.useEffect)((()=>(!R&&C&&null!=T&&window.docusaurus.prefetch(T),()=>{R&&O.current&&O.current.disconnect()})),[O,T,R,C]);const I=T?.startsWith("#")??!1,D=!T||!C||I;return D||g||E.collectLink(T),D?o.createElement("a",(0,r.Z)({ref:S,href:T},x&&!C&&{target:"_blank",rel:"noopener noreferrer"},b)):o.createElement(P,(0,r.Z)({},b,{onMouseEnter:N,onTouchStart:N,innerRef:e=>{S.current=e,R&&e&&C&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),O.current.observe(e))},to:T},n&&{isActive:m,activeClassName:h}))}const f=o.forwardRef(p)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>s,I:()=>l});var r=n(7294);function o(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 a=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 a[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return o(i({message:n,id:r}),t)}function s(e){let{children:t,id:n,values:a}=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,o(l,a))}},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 o(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>o,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>l});var r=n(7294),o=n(2263),a=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,o.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a.b)(n))return n;if(o)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:()=>a});var r=n(7294),o=n(8940);function a(){return(0,r.useContext)(o._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r=n(7294),o=n(8934);function a(){return(0,r.useContext)(o._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const l=o?`${o}.${a}`:a;r(i)?e(i,l):t[l]=i}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,z:()=>a});var r=n(7294);const o=r.createContext(null);function a(e){let{children:t,value:n}=e;const a=r.useContext(o),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:a,value:n})),[a,n]);return r.createElement(o.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>m,gA:()=>p,_r:()=>c,Jo:()=>g,zh:()=>d,yW:()=>h,gB:()=>f});var r=n(6550),o=n(2263),a=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const l=e=>e.versions.find((e=>e.isLast));function s(e,t){const n=function(e,t){const n=l(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),o=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const u={},c=()=>i("docusaurus-plugin-content-docs")??u,d=e=>function(e,t,n){void 0===t&&(t=a.m),void 0===n&&(n={});const r=i(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=c(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const o=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})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&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 a}(t,n,e)}function f(e){return d(e).versions}function h(e){const t=d(e);return l(t)}function m(e){const t=d(e),{pathname:n}=(0,r.TH)();return s(t,n)}function g(e){const t=d(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=l(e);return{latestDocSuggestion:s(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(4865),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),o=n(6809);!function(e){const{themeConfig:{prism:t}}=o.default,{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:()=>a});var r=n(7294);const o={iconExternalLink:"iconExternalLink_nPIU"};function a(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:o.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"}))}},179:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Ot});var r=n(7294),o=n(6010),a=n(4763),i=n(1944),l=n(7462),s=n(6550),u=n(5999),c=n(5936);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){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&&p(t)}),[]);return(0,c.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const h=(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 m(e){const t=e.children??h,{containerRef:n,onClick:o}=f();return r.createElement("div",{ref:n,role:"region","aria-label":h},r.createElement("a",(0,l.Z)({},e,{href:`#${d}`,onClick:o}),t))}var g=n(5281),v=n(9727);const b={skipToContent:"skipToContent_fXgn"};function y(){return r.createElement(m,{className:b.skipToContent})}var w=n(6668),k=n(9689);function E(e){let{width:t=21,height:n=21,color:o="currentColor",strokeWidth:a=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:o,strokeWidth:a},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,o.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,o.Z)(C.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function L(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,k.nT)();if(!t)return null;const{backgroundColor:o,textColor:a,isCloseable:i}=e;return r.createElement("div",{className:T.announcementBar,style:{backgroundColor:o,color:a},role:"banner"},i&&r.createElement("div",{className:T.announcementBarPlaceholder}),r.createElement(_,{className:T.announcementBarContent}),i&&r.createElement(x,{onClick:n,className:T.announcementBarClose}))}var A=n(2961),P=n(2466);var R=n(902),O=n(3102);const N=r.createContext(null);function I(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,O.HY)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,R.D9)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return r.createElement(N.Provider,{value:n},t)}function D(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function M(){const e=(0,r.useContext)(N);if(!e)throw new R.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,O.HY)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:D(a)})),[o,a,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:a}=e;const{shown:i}=M();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,o.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"},a)))}var j=n(2949),B=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 $(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 G={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function U(e){let{className:t,buttonClassName:n,value:a,onChange:i}=e;const l=(0,B.Z)(),s=(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"===a?(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,o.Z)(G.toggle,t)},r.createElement("button",{className:(0,o.Z)("clean-btn",G.toggleButton,!l&&G.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===a?"light":"dark"),disabled:!l,title:s,"aria-label":s,"aria-live":"polite"},r.createElement(z,{className:(0,o.Z)(G.toggleIcon,G.lightToggleIcon)}),r.createElement($,{className:(0,o.Z)(G.toggleIcon,G.darkToggleIcon)})))}const H=r.memo(U),q={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function Q(e){let{className:t}=e;const n=(0,w.L)().navbar.style,o=(0,w.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:i}=(0,j.I)();return o?null:r.createElement(H,{className:t,buttonClassName:"dark"===n?q.darkNavbarColorModeToggle:void 0,value:a,onChange:i})}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,A.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 K(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(V,null),r.createElement(Q,{className:"margin-right--md"}),r.createElement(W,null))}var Y=n(9960),X=n(4996),J=n(3919);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:o,href:a,label:i,html:s,isDropdownLink:u,prependBaseUrlToHref:c,...d}=e;const p=(0,X.Z)(o),f=(0,X.Z)(t),h=(0,X.Z)(a,{forcePrependBaseUrl:!0}),m=i&&a&&!(0,J.Z)(a),g=s?{dangerouslySetInnerHTML:{__html:s}}:{children:r.createElement(r.Fragment,null,i,m&&r.createElement(te.Z,u&&{width:12,height:12}))};return a?r.createElement(Y.Z,(0,l.Z)({href:c?h:a},d,g)):r.createElement(Y.Z,(0,l.Z)({to:p,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(f)},d,g))}function re(e){let{className:t,isDropdownItem:n=!1,...a}=e;const i=r.createElement(ne,(0,l.Z)({className:(0,o.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},a));return n?r.createElement("li",null,i):i}function oe(e){let{className:t,isDropdownItem:n,...a}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(ne,(0,l.Z)({className:(0,o.Z)("menu__link",t)},a)))}function ae(e){let{mobile:t=!1,position:n,...o}=e;const a=t?oe:re;return r.createElement(a,(0,l.Z)({},o,{activeClassName:o.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var ie=n(6043),le=n(8596),se=n(2263);function ue(e,t){return e.some((e=>function(e,t){return!!(0,le.Mg)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ce(e){let{items:t,position:n,className:a,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.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[u]),r.createElement("div",{ref:u,className:(0,o.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c})},r.createElement(ne,(0,l.Z)({"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,o.Z)("navbar__link",a)},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,t)=>r.createElement(qe,(0,l.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function de(e){let{items:t,className:n,position:a,onClick:i,...u}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,se.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:h}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&h(!d)}),[c,d,h]),r.createElement("li",{className:(0,o.Z)("menu__list-item",{"menu__list-item--collapsed":p})},r.createElement(ne,(0,l.Z)({role:"button",className:(0,o.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},u,{onClick:e=>{e.preventDefault(),f()}}),u.children??u.label),r.createElement(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p},t.map(((e,t)=>r.createElement(qe,(0,l.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function pe(e){let{mobile:t=!1,...n}=e;const o=t?de:ce;return r.createElement(o,n)}var fe=n(4711);function he(e){let{width:t=20,height:n=20,...o}=e;return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},o),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_nlXk";var ge=n(1029),ve=n(412),be=n(373),ye=n(143),we=n(22),ke=n(8202),Ee=n(3926),Se=n(1073),xe=n(2539),Ce=n(726);const _e='',Te='',Le='',Ae='',Pe='',Re='',Oe='',Ne={searchBar:"searchBar_RVTs",dropdownMenu:"dropdownMenu_qbY6",searchBarLeft:"searchBarLeft_MXDe",suggestion:"suggestion_fB_2",cursor:"cursor_eG29",hitTree:"hitTree_kk6K",hitIcon:"hitIcon_a7Zy",hitPath:"hitPath_ieM4",noResultsIcon:"noResultsIcon_EBY5",hitFooter:"hitFooter_E9YW",hitWrapper:"hitWrapper_sAK8",hitTitle:"hitTitle_vyVt",hitAction:"hitAction_NqkB",hideAction:"hideAction_vcyE",noResults:"noResults_l6Q3",searchBarContainer:"searchBarContainer_NW3z",searchBarLoadingRing:"searchBarLoadingRing_YnHq",searchClearButton:"searchClearButton_qk4g",searchIndexLoading:"searchIndexLoading_EJ1f",searchHintContainer:"searchHintContainer_Pkmr",searchHint:"searchHint_iIMx",focused:"focused_OWtg",input:"input_FOTf",hint:"hint_URu1",suggestions:"suggestions_X8XU",dataset:"dataset_QiCy",empty:"empty_eITn"};function Ie(e){let{document:t,type:n,page:r,metadata:o,tokens:a,isInterOfTree:i,isLastOfTree:l}=e;const s=0===n,u=1===n,c=[];i?c.push(Re):l&&c.push(Oe);const d=c.map((e=>`${e}`)),p=`${s?_e:u?Te:Le}`,f=[`${(0,Ce.o)(t.t,(0,Se.m)(o,"t"),a)}`];if(!i&&!l&&ge.H6){const e=r?(r.b??[]).concat(r.t).concat(t.s&&t.s!==r.t?t.s:[]):t.b;f.push(`${(0,Ee.e)(e??[])}`)}else s||f.push(`${(0,xe.C)(r.t||(t.u.startsWith("/docs/api-reference/")?"API Reference":""),a)}`);const h=`${Ae}`;return[...d,p,``,...f,"",h].join("")}function De(){return`${Pe}${(0,u.I)({id:"theme.SearchBar.noResultsText",message:"No results"})}`}var Me=n(311);async function Fe(){const e=await Promise.all([n.e(8443),n.e(5525)]).then(n.t.bind(n,8443,23)),t=e.default;return t.noConflict?t.noConflict():e.noConflict&&e.noConflict(),t}const je="_highlight";const Be=function(e){let{handleSearchBarToggle:t}=e;const{siteConfig:{baseUrl:n}}=(0,se.Z)(),a=(0,ye.gA)();let i=n;try{const{preferredVersion:e}=(0,be.J)(a?.pluginId??ge.gQ);e&&!e.isLast&&(i=e.path+"/")}catch(D){if(ge.l9&&!(D instanceof R.i6))throw D}const l=(0,s.k6)(),c=(0,s.TH)(),d=(0,r.useRef)(null),p=(0,r.useRef)(new Map),f=(0,r.useRef)(!1),[h,m]=(0,r.useState)(!1),[g,v]=(0,r.useState)(!1),[b,y]=(0,r.useState)(""),w=(0,r.useRef)(null),k=(0,r.useRef)(""),[E,S]=(0,r.useState)("");(0,r.useEffect)((()=>{if(!Array.isArray(ge.Kc))return;let e="";if(c.pathname.startsWith(i)){const t=c.pathname.substring(i.length),n=ge.Kc.find((e=>t===e||t.startsWith(`${e}/`)));n&&(e=n)}k.current!==e&&(p.current.delete(e),k.current=e),S(e)}),[c.pathname,i]);const x=!!ge.hG&&Array.isArray(ge.Kc)&&""===E,C=(0,r.useCallback)((async()=>{if(x||p.current.get(E))return;p.current.set(E,"loading"),w.current?.autocomplete.destroy(),m(!0);const[{wrappedIndexes:e,zhDictionary:t},r]=await Promise.all([(0,we.w)(i,E),Fe()]);if(w.current=r(d.current,{hint:!1,autoselect:!0,openOnFocus:!0,cssClasses:{root:(0,o.Z)(Ne.searchBar,{[Ne.searchBarLeft]:"left"===ge.pu}),noPrefix:!0,dropdownMenu:Ne.dropdownMenu,input:Ne.input,hint:Ne.hint,suggestions:Ne.suggestions,suggestion:Ne.suggestion,cursor:Ne.cursor,dataset:Ne.dataset,empty:Ne.empty}},[{source:(0,ke.v)(e,t,ge.qo),templates:{suggestion:Ie,empty:De,footer:e=>{let{query:t,isEmpty:r}=e;if(r&&!E)return;const o=(e=>{let{query:t,isEmpty:r}=e;const o=document.createElement("a"),a=new URLSearchParams,s=(0,u.I)({id:"theme.SearchBar.seeAll",message:"See all results"}),c=(0,u.I)({id:"theme.SearchBar.seeAllOutsideContext",message:"See results outside {context}"},{context:E}),d=(0,u.I)({id:"theme.SearchBar.searchInContext",message:"See all results in {context}"},{context:E});let p;if(a.set("q",t),p=E&&r?c:E?d:s,Array.isArray(ge.Kc)&&!r&&a.set("ctx",E),i!==n){if(!i.startsWith(n))throw new Error(`Version url '${i}' does not start with base url '${n}', this is a bug of \`@easyops-cn/docusaurus-search-local\`, please report it.`);a.set("version",i.substring(n.length))}const f=`${n}search?${a.toString()}`;return o.href=f,o.textContent=p,o.addEventListener("click",(e=>{e.ctrlKey||e.metaKey||(e.preventDefault(),w.current?.autocomplete.close(),l.push(f))})),o})({query:t,isEmpty:r}),a=document.createElement("div");return a.className=Ne.hitFooter,a.appendChild(o),a}}}]).on("autocomplete:selected",(function(e,t){let{document:{u:n,h:r},tokens:o}=t;d.current?.blur();let a=n;if(ge.vc&&o.length>0){const e=new URLSearchParams;for(const t of o)e.append(je,t);a+=`?${e.toString()}`}r&&(a+=r),l.push(a)})).on("autocomplete:closed",(()=>{d.current?.blur()})),p.current.set(E,"done"),m(!1),f.current){const e=d.current;e.value&&w.current?.autocomplete.open(),e.focus()}}),[x,E,i,n,l]);(0,r.useEffect)((()=>{if(!ge.vc)return;const e=ve.Z.canUseDOM?new URLSearchParams(c.search).getAll(je):[];setTimeout((()=>{const t=document.querySelector("article");if(!t)return;const n=new ge.vc(t);n.unmark(),0!==e.length&&n.mark(e),y(e.join(" ")),w.current?.autocomplete.setVal(e.join(" "))}))}),[c.search,c.pathname]);const[_,T]=(0,r.useState)(!1),L=(0,r.useCallback)((()=>{f.current=!0,C(),T(!0),t?.(!0)}),[t,C]),A=(0,r.useCallback)((()=>{T(!1),t?.(!1)}),[t]),P=(0,r.useCallback)((()=>{C()}),[C]),O=(0,r.useCallback)((e=>{y(e.target.value),e.target.value&&v(!0)}),[]),N=!!ve.Z.canUseDOM&&/mac/i.test(navigator.userAgentData?.platform??navigator.platform);(0,r.useEffect)((()=>{if(!ge.AY)return;const e=e=>{!(N?e.metaKey:e.ctrlKey)||"k"!==e.key&&"K"!==e.key||(e.preventDefault(),d.current?.focus(),L())};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}}),[N,L]);const I=(0,r.useCallback)((()=>{const e=new URLSearchParams(c.search);e.delete(je);const t=e.toString(),n=c.pathname+(""!=t?`?${t}`:"")+c.hash;n!=c.pathname+c.search+c.hash&&l.push(n),y(""),w.current?.autocomplete.setVal("")}),[c.pathname,c.search,c.hash,l]);return r.createElement("div",{className:(0,o.Z)("navbar__search",Ne.searchBarContainer,{[Ne.searchIndexLoading]:h&&g,[Ne.focused]:_}),hidden:x},r.createElement("input",{placeholder:(0,u.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),"aria-label":"Search",className:"navbar__search-input",onMouseEnter:P,onFocus:L,onBlur:A,onChange:O,ref:d,value:b}),r.createElement(Me.Z,{className:Ne.searchBarLoadingRing}),ge.AY&&ge.t_&&(""!==b?r.createElement("button",{className:Ne.searchClearButton,onClick:I},"\u2715"):ve.Z.canUseDOM&&r.createElement("div",{className:Ne.searchHintContainer},r.createElement("kbd",{className:Ne.searchHint},N?"\u2318":"ctrl"),r.createElement("kbd",{className:Ne.searchHint},"K"))))},ze={searchBox:"searchBox_ZlJk"};function $e(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,o.Z)(n,ze.searchBox)},t)}var Ge=n(2802);const Ue=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:o,...a}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,se.Z)(),p=(0,fe.l)(),{search:f,hash:h}=(0,s.TH)(),m=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${h}`;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":""}})),...o],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(pe,(0,l.Z)({},a,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(he,{className:me}),g),items:m}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement($e,{className:n},r.createElement(Be,null))},dropdown:pe,html:function(e){let{value:t,className:n,mobile:a=!1,isDropdownItem:i=!1}=e;const l=i?"li":"div";return r.createElement(l,{className:(0,o.Z)({navbar__item:!a&&!i,"menu__list-item":a},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:o,...a}=e;const{activeDoc:i}=(0,ye.Iw)(o),s=(0,Ge.vY)(t,o);return null===s?null:r.createElement(ae,(0,l.Z)({exact:!0},a,{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:o,...a}=e;const{activeDoc:i}=(0,ye.Iw)(o),s=(0,Ge.oz)(t,o).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},a,{isActive:()=>i?.sidebar===t,label:n??s.label,to:s.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:o,...a}=e;const i=(0,Ge.lO)(o)[0],s=t??i.label,u=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(ae,(0,l.Z)({},a,{label:s,to:u}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:o,dropdownItemsBefore:a,dropdownItemsAfter:i,...c}=e;const{search:d,hash:p}=(0,s.TH)(),f=(0,ye.Iw)(n),h=(0,ye.gB)(n),{savePreferredVersionName:m}=(0,be.J)(n),g=[...a,...h.map((e=>{const t=f.alternateDocVersions[e.name]??Ue(e);return{label:e.label,to:`${t.path}${d}${p}`,isActive:()=>e===f.activeVersion,onClick:()=>m(e.name)}})),...i],v=(0,Ge.lO)(n)[0],b=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"}):v.label,y=t&&g.length>1?void 0:Ue(v).path;return g.length<=1?r.createElement(ae,(0,l.Z)({},c,{mobile:t,label:b,to:y,isActive:o?()=>!1:void 0})):r.createElement(pe,(0,l.Z)({},c,{mobile:t,label:b,to:y,items:g,isActive:o?()=>!1:void 0}))}};function qe(e){let{type:t,...n}=e;const o=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),a=He[o];if(!a)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(a,n)}function Qe(){const e=(0,A.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(qe,(0,l.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ze(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 Ve(){const e=0===(0,w.L)().navbar.items.length,t=M();return r.createElement(r.Fragment,null,!e&&r.createElement(Ze,{onClick:()=>t.hide()}),t.content)}function We(){const e=(0,A.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(K,null),primaryMenu:r.createElement(Qe,null),secondaryMenu:r.createElement(Ve,null)}):null}const Ke={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Ye(e){return r.createElement("div",(0,l.Z)({role:"presentation"},e,{className:(0,o.Z)("navbar-sidebar__backdrop",e.className)}))}function Xe(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.L)(),i=(0,A.e)(),{navbarRef:l,isNavbarVisible:s}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,P.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 o.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,o.Z)("navbar","navbar--fixed-top",n&&[Ke.navbarHideable,!s&&Ke.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown})},t,r.createElement(Ye,{onClick:i.toggle}),r.createElement(We,null))}var Je=n(8780);const et={errorBoundaryError:"errorBoundaryError_a6uf"};function tt(e){return r.createElement("button",(0,l.Z)({type:"button"},e),r.createElement(u.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function nt(e){let{error:t}=e;const n=(0,Je.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{className:et.errorBoundaryError},n)}class rt extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const ot="right";function at(e){let{width:t=30,height:n=30,className:o,...a}=e;return r.createElement("svg",(0,l.Z)({className:o,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},a),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function it(){const{toggle:e,shown:t}=(0,A.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(at,null))}const lt={colorModeToggle:"colorModeToggle_DEke"};function st(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(rt,{key:t,onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t})},r.createElement(qe,e)))))}function ut(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 ct(){const e=(0,A.e)(),t=(0,w.L)().navbar.items,[n,o]=function(e){function t(e){return"left"===(e.position??ot)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),a=t.find((e=>"search"===e.type));return r.createElement(ut,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(it,null),r.createElement(V,null),r.createElement(st,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(st,{items:o}),r.createElement(Q,{className:lt.colorModeToggle}),!a&&r.createElement($e,null,r.createElement(Be,null)))})}function dt(){return r.createElement(Xe,null,r.createElement(ct,null))}function pt(e){let{item:t}=e;const{to:n,href:o,label:a,prependBaseUrlToHref:i,...s}=t,u=(0,X.Z)(n),c=(0,X.Z)(o,{forcePrependBaseUrl:!0});return r.createElement(Y.Z,(0,l.Z)({className:"footer__link-item"},o?{href:i?c:o}:{to:u},s),a,o&&!(0,J.Z)(o)&&r.createElement(te.Z,null))}function ft(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(pt,{item:t}))}function ht(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(ft,{key:t,item:e})))))}function mt(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(ht,{key:t,column:e}))))}function gt(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function vt(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(pt,{item:t})}function bt(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(vt,{item:e}),t.length!==n+1&&r.createElement(gt,null))))))}function yt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(mt,{columns:t}):r.createElement(bt,{links:t})}var wt=n(941);const kt={footerLogoLink:"footerLogoLink_BH7S"};function Et(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),a={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(wt.Z,{className:(0,o.Z)("footer__logo",t.className),alt:t.alt,sources:a,width:t.width,height:t.height,style:t.style})}function St(e){let{logo:t}=e;return t.href?r.createElement(Y.Z,{href:t.href,className:kt.footerLogoLink,target:t.target},r.createElement(Et,{logo:t})):r.createElement(Et,{logo:t})}function xt(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function Ct(e){let{style:t,links:n,logo:a,copyright:i}=e;return r.createElement("footer",{className:(0,o.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(a||i)&&r.createElement("div",{className:"footer__bottom text--center"},a&&r.createElement("div",{className:"margin-bottom--sm"},a),i)))}function _t(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:o,style:a}=e;return r.createElement(Ct,{style:a,links:n&&n.length>0&&r.createElement(yt,{links:n}),logo:o&&r.createElement(St,{logo:o}),copyright:t&&r.createElement(xt,{copyright:t})})}const Tt=r.memo(_t),Lt=(0,R.Qc)([j.S,k.pl,P.OC,be.L5,i.VC,function(e){let{children:t}=e;return r.createElement(O.n2,null,r.createElement(A.M,null,r.createElement(I,null,t)))}]);function At(e){let{children:t}=e;return r.createElement(Lt,null,t)}function Pt(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("div",{className:"margin-vert--lg"},r.createElement(tt,{onClick:n,className:"button button--primary shadow--lw"})),r.createElement("hr",null),r.createElement("div",{className:"margin-vert--md"},r.createElement(nt,{error:t})))))}const Rt={mainWrapper:"mainWrapper_z2l0"};function Ot(e){const{children:t,noFooter:n,wrapperClassName:l,title:s,description:u}=e;return(0,v.t)(),r.createElement(At,null,r.createElement(i.d,{title:s,description:u}),r.createElement(y,null),r.createElement(L,null),r.createElement(dt,null),r.createElement("div",{id:d,className:(0,o.Z)(g.k.wrapper.main,Rt.mainWrapper,l)},r.createElement(a.Z,{fallback:e=>r.createElement(Pt,e)},t)),!n&&r.createElement(Tt,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),o=n(7294),a=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 a={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},l=o.createElement(u.Z,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?o.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:p,...f}=e,h=(0,i.Z)(u?.href||"/"),m=n?"":t,g=u?.alt??m;return o.createElement(a.Z,(0,r.Z)({to:h},f,u?.target&&{target:u.target}),u&&o.createElement(c,{logo:u,alt:g,imageClassName:d}),null!=n&&o.createElement("b",{className:p},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r=n(7294),o=n(5742);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return r.createElement(o.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),a&&r.createElement("meta",{name:"docusaurus_tag",content:a}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),a&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:a}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7462),o=n(7294),a=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,...p}=e,f=t?"dark"===n?["dark"]:["light"]:["light","dark"];return o.createElement(o.Fragment,null,f.map((e=>o.createElement("img",(0,r.Z)({key:e,src:u[e],alt:d,className:(0,a.Z)(s.themedImage,s[`themedImage--${e}`],c)},p)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>s,z:()=>g});var r=n(7462),o=n(7294),a=n(412),i=n(1442);const l="ease-in-out";function s(e){let{initialState:t}=e;const[n,r]=(0,o.useState)(t??!1),a=(0,o.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},c={display:"block",overflow:"visible",height:"auto"};function d(e,t){const n=t?u:c;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function p(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const a=(0,o.useRef)(!1);(0,o.useEffect)((()=>{const e=t.current;function o(){const t=e.scrollHeight,n=r?.duration??function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??l}`,height:`${t}px`}}function s(){const t=o();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return d(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function f(e){if(!a.Z.canUseDOM)return e?u:c}function h(e){let{as:t="div",collapsed:n,children:r,animation:a,onCollapseTransitionEnd:i,className:l,disableSSRStyle:s}=e;const u=(0,o.useRef)(null);return p({collapsibleRef:u,collapsed:n,animation:a}),o.createElement(t,{ref:u,style:s?void 0:f(n),onTransitionEnd:e=>{"height"===e.propertyName&&(d(u.current,n),i?.(n))},className:l},r)}function m(e){let{collapsed:t,...n}=e;const[a,i]=(0,o.useState)(!t),[l,s]=(0,o.useState)(t);return(0,o.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,o.useLayoutEffect)((()=>{a&&s(t)}),[a,t]),a?o.createElement(h,(0,r.Z)({},n,{collapsed:l})):null}function g(e){let{lazy:t,...n}=e;const r=t?m:h;return o.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>h,pl:()=>f});var r=n(7294),o=n(2389),a=n(12),i=n(902),l=n(6668);const s=(0,a.WA)("docusaurus.announcement.dismiss"),u=(0,a.WA)("docusaurus.announcement.id"),c=()=>"true"===s.get(),d=e=>s.set(String(e)),p=r.createContext(null);function f(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,l.L)(),t=(0,o.Z)(),[n,a]=(0,r.useState)((()=>!!t&&c()));(0,r.useEffect)((()=>{a(c())}),[]);const i=(0,r.useCallback)((()=>{d(!0),a(!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()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(p.Provider,{value:n},t)}function h(){const e=(0,r.useContext)(p);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>g,S:()=>m});var r=n(7294),o=n(412),a=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"},p=e=>e===d.dark?d.dark:d.light,f=e=>o.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e),h=e=>{c.set(p(e))};function m(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,l.L)(),[o,a]=(0,r.useState)(f(e));(0,r.useEffect)((()=>{t&&c.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&h(t)):(a(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",p(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=c.get();null!==t&&i(p(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:o,setColorMode:i,get isDarkTheme(){return o===d.dark},setLightTheme(){i(d.light)},setDarkTheme(){i(d.dark)}})),[o,i])}();return r.createElement(s.Provider,{value:n},t)}function g(){const e=(0,r.useContext)(s);if(null==e)throw new a.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:()=>b,L5:()=>g});var r=n(7294),o=n(143),a=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()}},p=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const f=r.createContext(null);function h(){const e=(0,o._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,l]=(0,r.useState)((()=>p(n)));(0,r.useEffect)((()=>{l(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(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,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),l((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function m(e){let{children:t}=e;const n=h();return r.createElement(f.Provider,{value:n},t)}function g(e){let{children:t}=e;return l.cE?r.createElement(m,null,t):r.createElement(r.Fragment,null,t)}function v(){const e=(0,r.useContext)(f);if(!e)throw new s.i6("DocsPreferredVersionContextProvider");return e}function b(e){void 0===e&&(e=a.m);const t=(0,o.zh)(e),[n,i]=v(),{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),o=n(902);const a=Symbol("EmptyContext"),i=r.createContext(a);function l(e){let{children:t,name:n,items:o}=e;const a=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return r.createElement(i.Provider,{value:a},t)}function s(){const e=(0,r.useContext)(i);if(e===a)throw new o.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>i});var r=n(7294),o=n(902);const a=r.createContext(null);function i(e){let{children:t,version:n}=e;return r.createElement(a.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(a);if(null===e)throw new o.i6("DocsVersionProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>p,e:()=>f});var r=n(7294),o=n(3102),a=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,o.HY)(),{items:t}=(0,u.L)().navbar;return 0===t.length&&!e.component}(),t=(0,a.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 p(e){let{children:t}=e;const n=d();return r.createElement(c.Provider,{value:n},t)}function f(){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),o=n(902);const a=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(a.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(a);if(!e)throw new o.i6("NavbarSecondaryMenuContentProvider");return e[0]}function s(e){let{component:t,props:n}=e;const i=(0,r.useContext)(a);if(!i)throw new o.i6("NavbarSecondaryMenuContentProvider");const[,l]=i,s=(0,o.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:()=>o,t:()=>a});var r=n(7294);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>u});var r=n(7294),o=n(412);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function l(){return o.Z.canUseDOM?window.innerWidth>i?a.desktop:a.mobile:a.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:{}}},1442:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},2802:(e,t,n)=>{"use strict";n.d(t,{MN:()=>C,Wl:()=>h,_F:()=>b,cE:()=>p,jA:()=>m,xz:()=>f,hI:()=>x,lO:()=>k,vY:()=>S,oz:()=>E,s1:()=>w});var r=n(7294),o=n(6550),a=n(8790),i=n(143),l=n(373),s=n(4477),u=n(1116);function c(e){return Array.from(new Set(e))}var d=n(8596);const p=!!i._r;function f(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 h(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=h(t);if(e)return e}}}function m(){const{pathname:e}=(0,o.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),v=(e,t)=>e.some((e=>b(e,t)));function b(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||v(e.items,t))}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.Mg)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.Mg)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function w(){const e=(0,u.V)(),{pathname:t}=(0,o.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),o=(0,i.yW)(e);return(0,r.useMemo)((()=>c([t,n,o].filter(Boolean))),[t,n,o])}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(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).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(`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,o.TH)(),i=t.routes,l=i.find((e=>(0,o.LX)(r.pathname,e)));if(!l)return null;const s=l.sidebar,u=s?n.docsSidebars[s]:void 0;return{docElement:(0,a.H)(i),sidebarName:s,sidebarItems:u}}function C(e){return e.filter((e=>"category"!==e.type||!!h(e)))}},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>p,d:()=>c,VC:()=>f});var r=n(7294),o=n(6010),a=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:o,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)(),p=i?d(i,{absolute:!0}):void 0;return r.createElement(a.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}),o&&r.createElement("meta",{name:"keywords",content:Array.isArray(o)?o.join(","):o}),p&&r.createElement("meta",{property:"og:image",content:p}),p&&r.createElement("meta",{name:"twitter:image",content:p}),l)}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),l=(0,o.Z)(i,t);return r.createElement(d.Provider,{value:l},r.createElement(a.Z,null,r.createElement("html",{className:l})),n)}function f(e){let{children:t}=e;const n=l(),a=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(p,{className:(0,o.Z)(a,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>u,Ql:()=>s,i6:()=>l,zX:()=>a});var r=n(7294);const o=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function a(e){const t=(0,r.useRef)(e);return o((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return o((()=>{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),o=n(723),a=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,a.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 o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>p,OC:()=>s,RF:()=>d});var r=n(7294),o=n(412),a=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=()=>o.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),o=(0,r.useRef)(c()),a=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=c();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function p(){const e=(0,r.useRef)(null),t=(0,a.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 o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>r,os:()=>o});n(2263);const r="default";function o(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 o(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function a(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=a(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),o({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),o({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:()=>i});var r=n(2263),o=n(6550),a=n(8780);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:l}}=(0,r.Z)(),{pathname:s}=(0,o.TH)(),u=(0,a.applyTrailingSlash)(s,{trailingSlash:n,baseUrl:e}),c=l===i?e:e.replace(`/${l}/`,"/"),d=u.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${c}`:`${c}${e}/`}(n)}${d}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),o=n(6550),a=n(902);function i(e){const t=(0,o.TH)(),n=(0,a.D9)(t),i=(0,a.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:()=>o});var r=n(2263);function o(){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[o]=e.split(/[#?]/),a="/"===o||o===r?o:(i=o,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(o,a)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},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.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}});var a=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return a.getErrorCausalChain}})},311:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(7294),o=n(6010);const a={loadingRing:"loadingRing_RJI3","loading-ring":"loading-ring_FB5o"};function i(e){let{className:t}=e;return r.createElement("div",{className:(0,o.Z)(a.loadingRing,t)},r.createElement("div",null),r.createElement("div",null),r.createElement("div",null),r.createElement("div",null))}},22:(e,t,n)=>{"use strict";n.d(t,{w:()=>l});var r=n(1336),o=n.n(r),a=n(1029);const i=new Map;function l(e,t){const n=`${e}${t}`;let r=i.get(n);return r||(r=async function(e,t){{const n=`${e}${a.J.replace("{dir}",t?`-${t.replace(/\//g,"-")}`:"")}`;if(new URL(n,location.origin).origin!==location.origin)throw new Error("Unexpected version url");const r=await(await fetch(n)).json(),i=r.map(((e,t)=>{let{documents:n,index:r}=e;return{type:t,documents:n,index:o().Index.load(r)}})),l=r.reduce(((e,t)=>{for(const n of t.index.invertedIndex)/\p{Unified_Ideograph}/u.test(n[0][0])&&e.add(n[0]);return e}),new Set);return{wrappedIndexes:i,zhDictionary:Array.from(l)}}return{wrappedIndexes:[],zhDictionary:[]}}(e,t),i.set(n,r)),r}},8202:(e,t,n)=>{"use strict";n.d(t,{v:()=>s});var r=n(1336),o=n.n(r);var a=n(1029);function i(e){return l(e).concat(l(e.filter((e=>{const t=e[e.length-1];return!t.trailing&&t.maybeTyping})),!0))}function l(e,t){return e.map((e=>({tokens:e.map((e=>e.value)),term:e.map((e=>({value:e.value,presence:o().Query.presence.REQUIRED,wildcard:(t?e.trailing||e.maybeTyping:e.trailing)?o().Query.wildcard.TRAILING:o().Query.wildcard.NONE})))})))}function s(e,t,n){return function(r,l){const s=function(e,t){if(1===t.length&&["ja","jp","th"].includes(t[0]))return o()[t[0]].tokenizer(e).map((e=>e.toString()));let n=/[^-\s]+/g;return t.includes("zh")&&(n=/\w+|\p{Unified_Ideograph}+/gu),e.toLowerCase().match(n)||[]}(r,a.dK);if(0===s.length)return void l([]);const u=function(e,t){const n=function(e,t){const n=[];return function e(r,o){if(0===r.length)return void n.push(o);const a=r[0];if(/\p{Unified_Ideograph}/u.test(a)){const n=function(e,t){const n=[];return function e(r,o){let a=0,i=!1;for(const l of t)if(r.substr(0,l.length)===l){const t={missed:o.missed,term:o.term.concat({value:l})};r.length>l.length?e(r.substr(l.length),t):n.push(t),i=!0}else for(let t=l.length-1;t>a;t-=1){const s=l.substr(0,t);if(r.substr(0,t)===s){a=t;const l={missed:o.missed,term:o.term.concat({value:s,trailing:!0})};r.length>t?e(r.substr(t),l):n.push(l),i=!0;break}}i||(r.length>0?e(r.substr(1),{missed:o.missed+1,term:o.term}):o.term.length>0&&n.push(o))}(e,{missed:0,term:[]}),n.sort(((e,t)=>{const n=e.missed>0?1:0,r=t.missed>0?1:0;return n!==r?n-r:e.term.length-t.term.length})).map((e=>e.term))}(a,t);for(const t of n){const n=o.concat(...t);e(r.slice(1),n)}}else{const t=o.concat({value:a});e(r.slice(1),t)}}(e,[]),n}(e,t);if(0===n.length)return[{tokens:e,term:e.map((e=>({value:e,presence:o().Query.presence.REQUIRED,wildcard:o().Query.wildcard.LEADING|o().Query.wildcard.TRAILING})))}];for(const o of n)o[o.length-1].maybeTyping=!0;const r=[];for(const i of a.dK)if("en"===i)a._k||r.unshift(o().stopWordFilter);else{const e=o()[i];e.stopWordFilter&&r.unshift(e.stopWordFilter)}let l;if(r.length>0){const e=e=>r.reduce(((e,t)=>e.filter((e=>t(e.value)))),e);l=[];const t=[];for(const r of n){const n=e(r);l.push(n),n.length0&&t.push(n)}n.push(...t)}else l=n.slice();const s=[];for(const o of l)if(o.length>2)for(let e=o.length-1;e>=0;e-=1)s.push(o.slice(0,e).concat(o.slice(e+1)));return i(n).concat(i(s))}(s,t),c=[];e:for(const{term:t,tokens:o}of u)for(const{documents:r,index:a,type:i}of e)if(c.push(...a.query((e=>{for(const n of t)e.term(n.value,{wildcard:n.wildcard,presence:n.presence})})).slice(0,n).filter((e=>!c.some((t=>t.document.i.toString()===e.ref)))).slice(0,n-c.length).map((t=>{const n=r.find((e=>e.i.toString()===t.ref));return{document:n,type:i,page:0!==i&&e[0].documents.find((e=>e.i===n.p)),metadata:t.matchData.metadata,tokens:o,score:t.score}}))),c.length>=n)break e;!function(e){e.forEach(((e,t)=>{e.index=t})),e.sort(((t,n)=>{let r=t.type>0&&t.page?e.findIndex((e=>e.document===t.page)):t.index,o=n.type>0&&n.page?e.findIndex((e=>e.document===n.page)):n.index;return-1===r&&(r=t.index),-1===o&&(o=n.index),r===o?0===t.type?-1:0===n.type?1:t.index-n.index:r-o}))}(c),function(e){e.forEach(((t,n)=>{n>0&&t.page&&e.some((e=>e.document===t.page))&&(n{"use strict";function r(e){return e.join(" \u203a ")}n.d(t,{e:()=>r})},1690:(e,t,n)=>{"use strict";function r(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}n.d(t,{X:()=>r})},1073:(e,t,n)=>{"use strict";function r(e,t){const n=[];for(const r of Object.values(e))r[t]&&n.push(...r[t].position);return n.sort(((e,t)=>e[0]-t[0]||t[1]-e[1]))}n.d(t,{m:()=>r})},2539:(e,t,n)=>{"use strict";n.d(t,{C:()=>o});var r=n(1690);function o(e,t,n){const a=[];for(const i of t){const n=e.toLowerCase().indexOf(i);if(n>=0){n>0&&a.push(o(e.substr(0,n),t)),a.push(`${(0,r.X)(e.substr(n,i.length))}`);const l=n+i.length;l${(0,r.X)(e)}`:(0,r.X)(e):a.join("")}},726:(e,t,n)=>{"use strict";n.d(t,{o:()=>s});var r=n(1690),o=n(2539);const a=/\w+|\p{Unified_Ideograph}/u;function i(e){const t=[];let n=0,r=e;for(;r.length>0;){const o=r.match(a);if(!o){t.push(r);break}o.index>0&&t.push(r.substring(0,o.index)),t.push(o[0]),n+=o.index+o[0].length,r=e.substring(n)}return t}var l=n(1029);function s(e,t,n,a){void 0===a&&(a=l.Hk);const{chunkIndex:s,chunks:u}=function(e,t,n){const a=[];let l=0,s=0,u=-1;for(;ls){const t=i(e.substring(s,c)).map((e=>({html:(0,r.X)(e),textLength:e.length})));for(const e of t)a.push(e)}-1===u&&(u=a.length),s=c+d,a.push({html:(0,o.C)(e.substring(c,s),n,!0),textLength:d})}}if(s({html:(0,r.X)(e),textLength:e.length})));for(const e of t)a.push(e)}return{chunkIndex:u,chunks:a}}(e,t,n),c=u.slice(0,s),d=u[s],p=[d.html],f=u.slice(s+1);let h=d.textLength,m=0,g=0,v=!1,b=!1;for(;h0){const e=c.pop();h+e.textLength<=a?(p.unshift(e.html),m+=e.textLength,h+=e.textLength):(v=!0,c.length=0)}else{if(!(f.length>0))break;{const e=f.shift();h+e.textLength<=a?(p.push(e.html),g+=e.textLength,h+=e.textLength):(b=!0,f.length=0)}}return(v||c.length>0)&&p.unshift("\u2026"),(b||f.length>0)&&p.push("\u2026"),p.join("")}},1029:(e,t,n)=>{"use strict";n.d(t,{vc:()=>a,gQ:()=>f,H6:()=>u,hG:()=>g,l9:()=>h,dK:()=>r,_k:()=>o,pu:()=>p,AY:()=>c,t_:()=>d,Kc:()=>m,J:()=>i,Hk:()=>s,qo:()=>l,pQ:()=>v});n(1336);const r=["en"],o=!1,a=null,i="search-index{dir}.json?_=2e11f48b",l=8,s=50,u=!1,c=!0,d=!0,p="right",f=void 0,h=!0,m=null,g=!1,v=!1},6010:(e,t,n)=>{"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;to});const o=function(){for(var e,t,n=0,o="";n{"use strict";n.d(t,{lX:()=>w,q_:()=>_,ob:()=>f,PP:()=>L,Ep:()=>p});var r=n(7462);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!u)for(;d--;d)i.unshift("..");!u||""===i[0]||i[0]&&o(i[0])||i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};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 p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.Z)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function h(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!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,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,m(),w.location);c.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},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),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={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]||o}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,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=f(n);o&&o!==h&&e(t,o,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=s(t),m=s(n),g=0;g{"use strict";e.exports=function(e,t,n,r,o,a,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,o,a,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)}},1336:(e,t,n)=>{var r,o;!function(){var a,i,l,s,u,c,d,p,f,h,m,g,v,b,y,w,k,E,S,x,C,_,T,L,A,P,R,O,N,I,D=function(e){var t=new D.Builder;return t.pipeline.add(D.trimmer,D.stopWordFilter,D.stemmer),t.searchPipeline.add(D.stemmer),e.call(t,t),t.build()};D.version="2.3.9",D.utils={},D.utils.warn=(a=this,function(e){a.console&&console.warn&&console.warn(e)}),D.utils.asString=function(e){return null==e?"":e.toString()},D.utils.clone=function(e){if(null==e)return e;for(var t=Object.create(null),n=Object.keys(e),r=0;r0){var s=D.utils.clone(t)||{};s.position=[i,l],s.index=o.length,o.push(new D.Token(n.slice(i,a),s))}i=a+1}}return o},D.tokenizer.separator=/[\s\-]+/,D.Pipeline=function(){this._stack=[]},D.Pipeline.registeredFunctions=Object.create(null),D.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&D.utils.warn("Overwriting existing registered function: "+t),e.label=t,D.Pipeline.registeredFunctions[e.label]=e},D.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||D.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},D.Pipeline.load=function(e){var t=new D.Pipeline;return e.forEach((function(e){var n=D.Pipeline.registeredFunctions[e];if(!n)throw new Error("Cannot load unregistered function: "+e);t.add(n)})),t},D.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach((function(e){D.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},D.Pipeline.prototype.after=function(e,t){D.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");n+=1,this._stack.splice(n,0,t)},D.Pipeline.prototype.before=function(e,t){D.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");this._stack.splice(n,0,t)},D.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},D.Pipeline.prototype.run=function(e){for(var t=this._stack.length,n=0;n1&&(ae&&(n=o),a!=e);)r=n-t,o=t+Math.floor(r/2),a=this.elements[2*o];return a==e||a>e?2*o:al?u+=2:i==l&&(t+=n[s+1]*r[u+1],s+=2,u+=2);return t},D.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},D.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,n=0;t0){var a,i=o.str.charAt(0);i in o.node.edges?a=o.node.edges[i]:(a=new D.TokenSet,o.node.edges[i]=a),1==o.str.length&&(a.final=!0),r.push({node:a,editsRemaining:o.editsRemaining,str:o.str.slice(1)})}if(0!=o.editsRemaining){if("*"in o.node.edges)var l=o.node.edges["*"];else{l=new D.TokenSet;o.node.edges["*"]=l}if(0==o.str.length&&(l.final=!0),r.push({node:l,editsRemaining:o.editsRemaining-1,str:o.str}),o.str.length>1&&r.push({node:o.node,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)}),1==o.str.length&&(o.node.final=!0),o.str.length>=1){if("*"in o.node.edges)var s=o.node.edges["*"];else{s=new D.TokenSet;o.node.edges["*"]=s}1==o.str.length&&(s.final=!0),r.push({node:s,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)})}if(o.str.length>1){var u,c=o.str.charAt(0),d=o.str.charAt(1);d in o.node.edges?u=o.node.edges[d]:(u=new D.TokenSet,o.node.edges[d]=u),1==o.str.length&&(u.final=!0),r.push({node:u,editsRemaining:o.editsRemaining-1,str:c+o.str.slice(2)})}}}return n},D.TokenSet.fromString=function(e){for(var t=new D.TokenSet,n=t,r=0,o=e.length;r=e;t--){var n=this.uncheckedNodes[t],r=n.child.toString();r in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[r]:(n.child._str=r,this.minimizedNodes[r]=n.child),this.uncheckedNodes.pop()}},D.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},D.Index.prototype.search=function(e){return this.query((function(t){new D.QueryParser(e,t).parse()}))},D.Index.prototype.query=function(e){for(var t=new D.Query(this.fields),n=Object.create(null),r=Object.create(null),o=Object.create(null),a=Object.create(null),i=Object.create(null),l=0;l1?1:e},D.Builder.prototype.k1=function(e){this._k1=e},D.Builder.prototype.add=function(e,t){var n=e[this._ref],r=Object.keys(this._fields);this._documents[n]=t||{},this.documentCount+=1;for(var o=0;o=this.length)return D.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},D.QueryLexer.prototype.width=function(){return this.pos-this.start},D.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},D.QueryLexer.prototype.backup=function(){this.pos-=1},D.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=D.QueryLexer.EOS&&this.backup()},D.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(D.QueryLexer.TERM)),e.ignore(),e.more())return D.QueryLexer.lexText},D.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(D.QueryLexer.EDIT_DISTANCE),D.QueryLexer.lexText},D.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(D.QueryLexer.BOOST),D.QueryLexer.lexText},D.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(D.QueryLexer.TERM)},D.QueryLexer.termSeparator=D.tokenizer.separator,D.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==D.QueryLexer.EOS)return D.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return D.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(D.QueryLexer.TERM),D.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(D.QueryLexer.TERM),D.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(D.QueryLexer.PRESENCE),D.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(D.QueryLexer.PRESENCE),D.QueryLexer.lexText;if(t.match(D.QueryLexer.termSeparator))return D.QueryLexer.lexTerm}else e.escapeCharacter()}},D.QueryParser=function(e,t){this.lexer=new D.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},D.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=D.QueryParser.parseClause;e;)e=e(this);return this.query},D.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},D.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},D.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},D.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case D.QueryLexer.PRESENCE:return D.QueryParser.parsePresence;case D.QueryLexer.FIELD:return D.QueryParser.parseField;case D.QueryLexer.TERM:return D.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(n+=" with value '"+t.str+"'"),new D.QueryParseError(n,t.start,t.end)}},D.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=D.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=D.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+t.str+"'";throw new D.QueryParseError(n,t.start,t.end)}var r=e.peekLexeme();if(null==r){n="expecting term or field, found nothing";throw new D.QueryParseError(n,t.start,t.end)}switch(r.type){case D.QueryLexer.FIELD:return D.QueryParser.parseField;case D.QueryLexer.TERM:return D.QueryParser.parseTerm;default:n="expecting term or field, found '"+r.type+"'";throw new D.QueryParseError(n,r.start,r.end)}}},D.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var n=e.query.allFields.map((function(e){return"'"+e+"'"})).join(", "),r="unrecognised field '"+t.str+"', possible fields: "+n;throw new D.QueryParseError(r,t.start,t.end)}e.currentClause.fields=[t.str];var o=e.peekLexeme();if(null==o){r="expecting term, found nothing";throw new D.QueryParseError(r,t.start,t.end)}if(o.type===D.QueryLexer.TERM)return D.QueryParser.parseTerm;r="expecting term, found '"+o.type+"'";throw new D.QueryParseError(r,o.start,o.end)}},D.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(null!=n)switch(n.type){case D.QueryLexer.TERM:return e.nextClause(),D.QueryParser.parseTerm;case D.QueryLexer.FIELD:return e.nextClause(),D.QueryParser.parseField;case D.QueryLexer.EDIT_DISTANCE:return D.QueryParser.parseEditDistance;case D.QueryLexer.BOOST:return D.QueryParser.parseBoost;case D.QueryLexer.PRESENCE:return e.nextClause(),D.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+n.type+"'";throw new D.QueryParseError(r,n.start,n.end)}else e.nextClause()}},D.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="edit distance must be numeric";throw new D.QueryParseError(r,t.start,t.end)}e.currentClause.editDistance=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case D.QueryLexer.TERM:return e.nextClause(),D.QueryParser.parseTerm;case D.QueryLexer.FIELD:return e.nextClause(),D.QueryParser.parseField;case D.QueryLexer.EDIT_DISTANCE:return D.QueryParser.parseEditDistance;case D.QueryLexer.BOOST:return D.QueryParser.parseBoost;case D.QueryLexer.PRESENCE:return e.nextClause(),D.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new D.QueryParseError(r,o.start,o.end)}else e.nextClause()}},D.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="boost must be numeric";throw new D.QueryParseError(r,t.start,t.end)}e.currentClause.boost=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case D.QueryLexer.TERM:return e.nextClause(),D.QueryParser.parseTerm;case D.QueryLexer.FIELD:return e.nextClause(),D.QueryParser.parseField;case D.QueryLexer.EDIT_DISTANCE:return D.QueryParser.parseEditDistance;case D.QueryLexer.BOOST:return D.QueryParser.parseBoost;case D.QueryLexer.PRESENCE:return e.nextClause(),D.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new D.QueryParseError(r,o.start,o.end)}else e.nextClause()}},void 0===(o="function"==typeof(r=function(){return D})?r.call(t,n,t,e):r)||(e.exports=o)}()},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,o;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 o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}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=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),u=a.querySelector(r.barSelector),c=r.speed,d=r.easing;return a.offsetWidth,l((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,i(e,c,d)),1===e?(s(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){s(a,{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)*o(Math.random()*t,.1,.95)),t=o(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 o,i=t.querySelector(r.barSelector),l=e?"-100":a(n.status||0),u=document.querySelector(r.parent);return s(i,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),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&&f(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,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function u(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=p(e),r=n+t;u(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);u(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},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(o){return!1}}()?Object.assign:function(e,o){for(var a,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=f,e.exports.parse=a,e.exports.compile=function(e,t){return l(a(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=p;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,i=0,l="",c=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],p=n[1],f=n.index;if(l+=e.slice(i,f),i=f+d.length,p)l+=p[1];else{var h=e[i],m=n[2],g=n[3],v=n[4],b=n[5],y=n[6],w=n[7];l&&(r.push(l),l="");var k=null!=m&&null!=h&&h!==m,E="+"===y||"*"===y,S="?"===y||"*"===y,x=n[2]||c,C=v||b;r.push({name:g||a++,prefix:m||"",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:()=>a});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof o?new o(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 o)){var C,_=1;if(b){if(!(C=a(k,S,e,v))||C.index>=e.length)break;var T=C.index,L=C.index+C[0].length,A=S;for(A+=E.value.length;T>=A;)A+=(E=E.next).value.length;if(S=A-=E.value.length,E.value instanceof o)continue;for(var P=E;P!==t.tail&&(Ad.reach&&(d.reach=I);var D=E.prev;if(O&&(D=s(t,D,O),S+=O.length),u(t,D,_),E=s(t,D,new o(p,g?r.tokenize(R,g):R,y,R)),N&&s(t,E,N),_>1){var M={cause:p+","+h,reach:I};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,o={value:n,prev:t,next:r};return t.next=o,r.prev=o,e.length++,o}function u(e,t,n){for(var r=t.next,o=0;o"+a.content+""},r}(),o=r;r.default=r,o.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]},o.languages.markup.tag.inside["attr-value"].inside.entity=o.languages.markup.entity,o.languages.markup.doctype.inside["internal-subset"].inside=o.languages.markup,o.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(o.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:o.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:o.languages[t]};var a={};a[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},o.languages.insertBefore("markup","cdata",a)}}),Object.defineProperty(o.languages.markup.tag,"addAttribute",{value:function(e,t){o.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:o.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),o.languages.html=o.languages.markup,o.languages.mathml=o.languages.markup,o.languages.svg=o.languages.markup,o.languages.xml=o.languages.extend("markup",{}),o.languages.ssml=o.languages.xml,o.languages.atom=o.languages.xml,o.languages.rss=o.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 o=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=r.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},o.languages.c=o.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|[?:~]|[-+*/%&|^!=<>]=?/}),o.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),o.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},o.languages.c.string],char:o.languages.c.char,comment:o.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:o.languages.c}}}}),o.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 o.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"])}(o),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"))}(o),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},o={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:o,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:o})}(o),o.languages.javascript=o.languages.extend("clike",{"class-name":[o.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}|\?\?=?|\?\.?|[~:]/}),o.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,o.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:o.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:o.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:o.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:o.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:o.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),o.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:o.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"}}),o.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),o.languages.markup&&(o.languages.markup.tag.addInlined("script","javascript"),o.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")),o.languages.js=o.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}(o),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",o=/(?:[^\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})),a=/"(?:[^"\\\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"(?:"+o+"|"+a+")"}))),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(a),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}(o),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,o=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),a=/\|?[ \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("^"+o+a+"(?:"+o+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+o+a+")(?:"+o+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+o+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+o+"$"),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}(o),o.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:o.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+/},o.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=p(/^\{$/,/^\}$/);if(-1===l)continue;for(var s=n;s=0&&f(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,o=r.inside["interpolation-punctuation"],a=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 o={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",o),o.tokens=e.tokenize(o.code,o.grammar),e.hooks.run("after-tokenize",o),o.tokens}function u(t){var n={};n["interpolation-punctuation"]=o;var a=e.tokenize(t,n);if(3===a.length){var i=[1,1];i.push.apply(i,s(a[1],e.languages.javascript,"javascript")),a.splice.apply(a,i)}return new e.Token("interpolation",a,r.alias,t)}function c(t,n,r){var o=e.tokenize(t,{interpolation:{pattern:RegExp(a),lookbehind:!0}}),i=0,c={},d=s(o.map((function(e){if("string"==typeof e)return e;for(var n,o=e.content;-1!==t.indexOf(n=l(i++,r)););return c[n]=o,n})).join(""),n,r),p=Object.keys(c);return i=0,function e(t){for(var n=0;n=p.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var o=p[i],a="string"==typeof r?r:r.content,l=a.indexOf(o);if(-1!==l){++i;var s=a.substring(0,l),d=u(c[o]),f=a.substring(l+o.length),h=[];if(s&&h.push(s),h.push(d),f){var m=[f];e(m),h.push.apply(h,m)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(h)),n+=h.length-1):r.content=h}}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 p(e){return"string"==typeof e?e:Array.isArray(e)?e.map(p).join(""):p(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,o=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}(o),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 a(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return r})).replace(//g,(function(){return o})),RegExp(e,t)}o=a(o).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=a(/<\/?(?:[\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:a(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:a(/=/.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(o.content[0].content[1])&&n.pop():"/>"===o.content[o.content.length-1].content||n.push({tagName:i(o.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===o.type&&"{"===o.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===o.type&&"}"===o.content?n[n.length-1].openedBraces--:a=!0),(a||"string"==typeof o)&&n.length>0&&0===n[n.length-1].openedBraces){var s=i(o);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)}o.content&&"string"!=typeof o.content&&l(o.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||l(e.tokens)}))}(o),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],o=[];/^\w+$/.test(n)||o.push(/\w+/.exec(n)[0]),"diff"===n&&o.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:o,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})}(o),o.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},o.languages.go=o.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/}),o.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete o.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,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,l=i.length;-1!==n.code.indexOf(o=t(r,l));)++l;return i[l]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(l){for(var s=0;s=a.length);s++){var u=l[s];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=a[o],d=n.tokenStack[c],p="string"==typeof u?u:u.content,f=t(r,c),h=p.indexOf(f);if(h>-1){++o;var m=p.substring(0,h),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),v=p.substring(h+f.length),b=[];m&&b.push.apply(b,i([m])),b.push(g),v&&b.push.apply(b,i([v])),"string"==typeof u?l.splice.apply(l,[s,1].concat(b)):u.content=b}}else u.content&&i(u.content)}return l}(n.tokens)}}}})}(o),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}(o),o.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"}},o.languages.webmanifest=o.languages.json,o.languages.less=o.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:/[+\-*\/]/}),o.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),o.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:/[:;(){}]/},o.languages.objectivec=o.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 o.languages.objectivec["class-name"],o.languages.objc=o.languages.objectivec,o.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/},o.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:/[{}[\];(),.:]/},o.languages.python["string-interpolation"].inside.interpolation.inside.rest=o.languages.python,o.languages.py=o.languages.python,o.languages.reason=o.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/}),o.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 o.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}})}(o),o.languages.scss=o.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]+\}/}}}),o.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}]}),o.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),o.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}}),o.languages.scss.atrule.inside.rest=o.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:/[{}()\[\];:.]/}}(o),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}(o),o.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 a=o},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),o=n(9642),a=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...a,...Object.keys(Prism.languages)];o(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),a.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=6726},6500:(e,t,n)=>{var r={"./":2885};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.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 o(t,a),l[t]=!0,n[t])l[i]=!0}t(s.require,u),t(s.optional,u),t(s.modify,u)}n[r]=l,a.pop()}}return function(e){var t=n[e];return t||(o(e,r),t=n[e]),t}}function o(e){for(var t in e)return!0;return!1}return function(a,i,l){var s=function(e){var t={};for(var n in e){var r=e[n];for(var o in r)if("meta"!=o){var a=r[o];t[o]="string"==typeof a?{title:a}:a}}return t}(a),u=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var o in n={},e){var a=e[o];t(a&&a.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+o+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+o+" because it is a component.");n[t]=o}))}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 p,f=r(s),h=c;o(h);){for(var m in p={},h){var g=s[m];t(g&&g.modify,(function(e){e in d&&(p[e]=!0)}))}for(var v in d)if(!(v in c))for(var b in f(v))if(b in c){p[v]=!0;break}for(var y in h=p)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,o){var a=o?o.series:void 0,i=o?o.parallel:e,l={},s={};function u(e){if(e in l)return l[e];s[e]=!0;var o,c=[];for(var d in t(e))d in n&&c.push(d);if(0===c.length)o=r(e);else{var p=i(c.map((function(e){var t=u(e);return delete s[e],t})));a?o=a(p,(function(){return r(e)})):r(e)}return l[e]=o}for(var c in n)u(c);var d=[];for(var p in s)d.push(l[p]);return i(d)}(f,c,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,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:a,resetWarningCache:o};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),o=n(7418),a=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n