diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..6e806f73 --- /dev/null +++ b/404.html @@ -0,0 +1,20 @@ + + + + + + 404 | Melange for React Devs + + + + + + + + + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
+ + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..2c5ee2bb --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +react-book.melange.re diff --git a/README.html b/README.html new file mode 100644 index 00000000..dae5a49f --- /dev/null +++ b/README.html @@ -0,0 +1,23 @@ + + + + + + Melange for React Developers Book | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Melange for React Developers Book

Installation

bash
make install
make install

Commands

Serve the site at http://localhost:5173/

bash
make serve
make serve
+ + + + \ No newline at end of file diff --git a/assets/README.md.3ce0111a.js b/assets/README.md.3ce0111a.js new file mode 100644 index 00000000..8baa435c --- /dev/null +++ b/assets/README.md.3ce0111a.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as s,Q as o}from"./chunks/framework.0e8ae64e.js";const k=JSON.parse('{"title":"Melange for React Developers Book","description":"","frontmatter":{},"headers":[],"relativePath":"README.md","filePath":"README.md"}'),t={name:"README.md"},l=o('

Melange for React Developers Book

Installation

bash
make install
make install

Commands

Serve the site at http://localhost:5173/

bash
make serve
make serve
',6),n=[l];function r(p,c,i,d,h,m){return e(),s("div",null,n)}const v=a(t,[["render",r]]);export{k as __pageData,v as default}; diff --git a/assets/README.md.3ce0111a.lean.js b/assets/README.md.3ce0111a.lean.js new file mode 100644 index 00000000..c9f84f1f --- /dev/null +++ b/assets/README.md.3ce0111a.lean.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as s,Q as o}from"./chunks/framework.0e8ae64e.js";const k=JSON.parse('{"title":"Melange for React Developers Book","description":"","frontmatter":{},"headers":[],"relativePath":"README.md","filePath":"README.md"}'),t={name:"README.md"},l=o("",6),n=[l];function r(p,c,i,d,h,m){return e(),s("div",null,n)}const v=a(t,[["render",r]]);export{k as __pageData,v as default}; diff --git a/assets/app.93f764dc.js b/assets/app.93f764dc.js new file mode 100644 index 00000000..b8559875 --- /dev/null +++ b/assets/app.93f764dc.js @@ -0,0 +1 @@ +import{s,a3 as i,a4 as u,a5 as c,a6 as l,a7 as d,a8 as f,a9 as m,aa as h,ab as A,ac as g,X as P,d as v,u as y,j as C,y as w,ad as _,ae as b,af as E,ag as R}from"./chunks/framework.0e8ae64e.js";import{t as D}from"./chunks/theme.802a1aee.js";function p(e){if(e.extends){const a=p(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const o=p(D),j=v({name:"VitePressApp",setup(){const{site:e}=y();return C(()=>{w(()=>{document.documentElement.lang=e.value.lang,document.documentElement.dir=e.value.dir})}),_(),b(),E(),o.setup&&o.setup(),()=>R(o.Layout)}});async function O(){const e=T(),a=S();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",d),a.component("ClientOnly",f),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),o.enhanceApp&&await o.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function S(){return h(j)}function T(){let e=s,a;return A(t=>{let n=g(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=P(()=>import(n),[])),s&&(e=!1),r},o.NotFound)}s&&O().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{O as createApp}; diff --git a/assets/celsius-converter-exception_index.md.ba9a3483.js b/assets/celsius-converter-exception_index.md.ba9a3483.js new file mode 100644 index 00000000..31cb318f --- /dev/null +++ b/assets/celsius-converter-exception_index.md.ba9a3483.js @@ -0,0 +1,289 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const F=JSON.parse('{"title":"Celsius Converter","description":"","frontmatter":{},"headers":[],"relativePath":"celsius-converter-exception/index.md","filePath":"celsius-converter-exception/index.md"}'),o={name:"celsius-converter-exception/index.md"},p=l(`

Celsius Converter

Our second widget will be one that takes a temperature value in Celsius and converts it to Fahrenheit. Create a new file called CelsiusConverter.re:

re
let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = ReactEvent.Form.target(evt)##value;
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};
let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = ReactEvent.Form.target(evt)##value;
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};

Inside the input’s onChange handler, we get the event target using ReactEvent.Form.target, which has the type ReactEvent.Form.t => {_.. }. What is {_.. }? It’s shorthand for the Js.t({..}) type[1], which consists of two parts:

Once we have a Js.t object, we can use the ## operator to access its fields. But beware, because the compiler knows nothing about the types of those fields. For example, we could write ReactEvent.Form.target(evt)##value + 1, treating it as if it were an integer, and the compiler wouldn’t complain.

Wrap functions that return Js.t

Instead of trusting ourselves to always use ReactEvent.Form.target(evt)##value correctly, it’s a good idea to wrap functions that return polymorphic objects into type-annotated helper functions. For example:

re
let getValueFromEvent = (evt): string =>
+  ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};
let getValueFromEvent = (evt): string =>
+  ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};

The : string after the argument list tells the compiler that this function must return a string. Using the getValueFromEvent function ensures that the value field can’t be used as anything other than a string.

Another thing to note about onChange is that after the evt argument, the body of the callback function is surrounded by braces ({}). OCaml functions are like JavaScript’s arrow functions—if they contain more than one line, they need to be enclosed by braces.

Apply pipe last (|>)

Let’s change the render logic to update the Fahrenheit display based on the value of celsius:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {celsius |> float_of_string |> convert |> string_of_float |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {celsius |> float_of_string |> convert |> string_of_float |> React.string}
+</div>;

The pipe last operator (|>) is very handy here, allowing us to convert a string to float, then convert that float to another float (Celsius -> Fahrenheit), convert back to string, and finally convert the string to React.element, all in one line.

String concatenation (++)

We should probably put °F after the Fahrenheit value so that it’s clear to the user what unit of measure they’re seeing. We can do so using the string concatenation operator (++):

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(celsius |> float_of_string |> convert |> string_of_float)
+   ++ {js|°F|js}
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(celsius |> float_of_string |> convert |> string_of_float)
+   ++ {js|°F|js}
+   |> React.string}
+</div>;

Catch exception with switch

However, there’s a bug in this code: it will crash if you enter anything into the input that can’t be converted to a float. We can remedy this by catching the exception using a switch expression:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception _ => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception _ => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;

The | exception _ branch will execute if there is any exception. The underscore (_) is a wildcard, meaning it will match any exception. If we wanted to be specific about which exception we want to catch, we could instead write

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception (Failure(_)) => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception (Failure(_)) => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;

Ternary expression

Right now it correctly renders “error” when you enter an invalid value, but it also renders “error” if the input is blank. It might be bit more user-friendly to instead show “?°F” like before. We can do that by wrapping the switch expression in a ternary expression:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert |> string_of_float) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert |> string_of_float) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

If-else expression

The ternary expression (condition ? a : b) works the same as in JavaScript. But in OCaml, it’s also shorthand for an if-else expression (if (condition) { a; } else { b; }). So we could rewrite it as this:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     if (celsius == "") {
+       {js|?°F|js};
+     } else {
+       switch (celsius |> float_of_string |> convert |> string_of_float) {
+       | exception _ => "error"
+       | fahrenheit => fahrenheit ++ {js|°F|js}
+       };
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     if (celsius == "") {
+       {js|?°F|js};
+     } else {
+       switch (celsius |> float_of_string |> convert |> string_of_float) {
+       | exception _ => "error"
+       | fahrenheit => fahrenheit ++ {js|°F|js}
+       };
+     }
+   )
+   |> React.string}
+</div>;

Unlike in JavaScript, the if-else construct is an expression and always yields a value. Both branches must return a value of the same type or you’ll get a compilation error. In practice, if-else expressions aren’t very common in OCaml code because in simple cases you can use ternary, and in more complex cases you can use switch. But it’s a nice, familiar fallback you can rely on when you haven’t quite gotten used to OCaml syntax yet.

Labeled argument

If we enter a value with a lot of decimals in it, e.g. 21.1223456, we’ll get a Fahrenheit value with a lot of decimals in it as well. We can limit the number of decimals in the converted value using Js.Float.toFixedWithPrecision:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert) {
+         | exception _ => "error"
+         | fahrenheit =>
+           Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2)
+           ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert) {
+         | exception _ => "error"
+         | fahrenheit =>
+           Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2)
+           ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

Js.Float.toFixedWithPrecision is a function that has one positional argument and one labeled argument. In this case, the labeled argument is named digits and it’s receiving a value of 2. It’s not possible to pass in the value of a labeled argument without using the ~label=value syntax. We’ll see more of labeled arguments in the following chapters when we introduce props.

Partial application

You might have noticed that the function chain feeding the switch expression got a bit shorter, from

reason
celsius |> float_of_string |> convert |> string_of_float
celsius |> float_of_string |> convert |> string_of_float

to

reason
celsius |> float_of_string |> convert
celsius |> float_of_string |> convert

This happened because string_of_float, which takes a single argument, was replaced by Js.Float.toFixedWithPrecision, which takes two arguments, and functions chained using |> can only take a single argument. But this one-argument restriction actually doesn’t prevent us from putting Js.Float.toFixedWithPrecision in the chain! We can take advantage of OCaml’s partial application feature to create a one-argument function by writing Js.Float.toFixedWithPrecision(~digits=2). Then our switch expression becomes

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (
+           celsius
+           |> float_of_string
+           |> convert
+           |> Js.Float.toFixedWithPrecision(~digits=2)
+         ) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (
+           celsius
+           |> float_of_string
+           |> convert
+           |> Js.Float.toFixedWithPrecision(~digits=2)
+         ) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

We have a working component now, but catching exceptions isn’t The OCaml Way! In the next chapter, you’ll see how to rewrite the logic using option.

Exercises

1. Try changing {js|°C = |js} to "°C = ". What happens?

2. It’s possible to rewrite the onChange callback so that it contains a single expression:

re
<input
+  value=celsius
+  onChange={evt => setCelsius(_ => getValueFromEvent(evt))}
+/>;
<input
+  value=celsius
+  onChange={evt => setCelsius(_ => getValueFromEvent(evt))}
+/>;

This compiles, but it now contains a hidden bug. Do you know what silent error might occur?

3. It’s possible to use partial application with most functions in OCaml, even operators. Take a look at the following program:

reason
let addFive = (+)(5);
+Js.log(addFive(2));
+Js.log(addFive(7));
+Js.log(addFive(10));
let addFive = (+)(5);
+Js.log(addFive(2));
+Js.log(addFive(7));
+Js.log(addFive(10));

What do you think it outputs? Run it in Melange Playground to confirm your hypothesis.

4. Use the pipe last operator (|>) and partial application to write a function that takes an integer argument x, subtracts x from 10, and converts that result to binary. Hint: Use the Js.Int.toStringWithRadix function.

Overview

Solutions

1. Changing it to "°C = " will result in a bit of gibberish being rendered: “°C”. We can’t rely on OCaml strings to deal with Unicode correctly, so any string that contains non-ASCII text must be delimited using {js||js}.

TIP

Note that quoted string literals using the js identifier are specific to Melange and are not available in native OCaml.

2. Rewriting onChange the handler to use a single expression creates a potential problem with stale values coming from the event object:

re
<input
+  value=celsius
+  onChange={evt =>
+    setCelsius(_ => {
+      // we are no longer in the scope of onChange
+      getValueFromEvent(evt)
+    })
+  }
+/>;
<input
+  value=celsius
+  onChange={evt =>
+    setCelsius(_ => {
+      // we are no longer in the scope of onChange
+      getValueFromEvent(evt)
+    })
+  }
+/>;

Inside of onChange, we can expect the function getValueFromEvent(evt) to return the latest value of the input. However, we are now calling getValueFromEvent(evt) from a different function—the callback we pass to setCelsius! By the time that setCelsius’s callback is invoked, the evt object might have been recycled and no longer have the same value as when onChange was initially invoked. For more details about this, see Using Event Values with useState in the ReasonReact docs.

3. Playground: Define an addFive function using partial application

4. Playground: Define a function that subtracts from 10 and converts to binary


Source code for this chapter can be found in the Melange for React Developers repo.


  1. See Using Js.t objects for more details. ↩︎

`,65),e=[p];function t(c,r,y,E,i,h){return n(),a("div",null,e)}const D=s(o,[["render",t]]);export{F as __pageData,D as default}; diff --git a/assets/celsius-converter-exception_index.md.ba9a3483.lean.js b/assets/celsius-converter-exception_index.md.ba9a3483.lean.js new file mode 100644 index 00000000..bf022388 --- /dev/null +++ b/assets/celsius-converter-exception_index.md.ba9a3483.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const F=JSON.parse('{"title":"Celsius Converter","description":"","frontmatter":{},"headers":[],"relativePath":"celsius-converter-exception/index.md","filePath":"celsius-converter-exception/index.md"}'),o={name:"celsius-converter-exception/index.md"},p=l("",65),e=[p];function t(c,r,y,E,i,h){return n(),a("div",null,e)}const D=s(o,[["render",t]]);export{F as __pageData,D as default}; diff --git a/assets/celsius-converter-option_index.md.df50f66c.js b/assets/celsius-converter-option_index.md.df50f66c.js new file mode 100644 index 00000000..0cc147fb --- /dev/null +++ b/assets/celsius-converter-option_index.md.df50f66c.js @@ -0,0 +1,239 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const D=JSON.parse('{"title":"Celsius Converter using Option","description":"","frontmatter":{},"headers":[],"relativePath":"celsius-converter-option/index.md","filePath":"celsius-converter-option/index.md"}'),o={name:"celsius-converter-option/index.md"},p=l(`

Celsius Converter using Option

After all the changes we made in the last chapter, your CelsiusConverter.re might look something like this:

re
let getValueFromEvent = (evt): string => ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {(
+       celsius == ""
+         ? {js|?°F|js}
+         : (
+           switch (
+             celsius
+             |> float_of_string
+             |> convert
+             |> Js.Float.toFixedWithPrecision(~digits=2)
+           ) {
+           | exception _ => "error"
+           | fahrenheit => fahrenheit ++ {js|°F|js}
+           }
+         )
+     )
+     |> React.string}
+  </div>;
+};
let getValueFromEvent = (evt): string => ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {(
+       celsius == ""
+         ? {js|?°F|js}
+         : (
+           switch (
+             celsius
+             |> float_of_string
+             |> convert
+             |> Js.Float.toFixedWithPrecision(~digits=2)
+           ) {
+           | exception _ => "error"
+           | fahrenheit => fahrenheit ++ {js|°F|js}
+           }
+         )
+     )
+     |> React.string}
+  </div>;
+};

What happens if you forget the | exception _ branch of your switch expression? Your program will crash when invalid input is entered. The compiler won’t warn you to add an exception branch because it doesn’t keep track of which functions throw exceptions. Next, we’ll show you a better way which completely avoids functions that can fail in unexpected ways.

float_of_string_opt

Refactor the switch expression to use float_of_string_opt instead. This function has the type signature string => option(float). It takes a string argument and returns Some(number) if it succeeds and None if it fails—meaning that even if this function fails, no exception is raised.

re
(
+  switch (celsius |> float_of_string_opt) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    (fahrenheit |> convert |> Js.Float.toFixedWithPrecision(~digits=2))
+    ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    (fahrenheit |> convert |> Js.Float.toFixedWithPrecision(~digits=2))
+    ++ {js|°F|js}
+  }
+)

In terms of functionality, this does exactly what the previous version did. But a critical difference is that if you comment out the | None branch, the compiler will refuse to accept it:

File "CelsiusConverter.re", lines 21-32, characters 11-10:
+21 | ...........(
+22 |            switch (celsius |> float_of_string_opt) {
+23 |            //  | None => "error"
+24 |            | Some(fahrenheit) =>
+25 |              (
+...
+29 |              )
+30 |              ++ {js| °F|js}
+31 |            }
+32 |          )
+Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None
File "CelsiusConverter.re", lines 21-32, characters 11-10:
+21 | ...........(
+22 |            switch (celsius |> float_of_string_opt) {
+23 |            //  | None => "error"
+24 |            | Some(fahrenheit) =>
+25 |              (
+...
+29 |              )
+30 |              ++ {js| °F|js}
+31 |            }
+32 |          )
+Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None

You would get a similar error if you left off the | Some(_) branch. Having an option value be the input for a switch expression means that you can’t forget to handle the failure case, much less the success case. There’s another advantage: The | Some(fahrenheit) branch gives you access to the float that was successfully converted from the string, and only this branch has access to that value. So you can be reasonably sure that the success case is handled here and not somewhere else. You are starting to experience the power of pattern matching in OCaml.

Option.map

It’s a shame we had to give up the long chain of function calls from when we were still using float_of_string:

reason
celsius
+|> float_of_string
+|> convert
+|> Js.Float.toFixedWithPrecision(~digits=2)
celsius
+|> float_of_string
+|> convert
+|> Js.Float.toFixedWithPrecision(~digits=2)

Actually, we can still use a very similar chain of functions with float_of_string_opt if we make a couple of small additions:

reason
celsius
+|> float_of_string_opt
+|> Option.map(convert)
+|> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
celsius
+|> float_of_string_opt
+|> Option.map(convert)
+|> Option.map(Js.Float.toFixedWithPrecision(~digits=2))

Option.map takes a function and an option value, and only invokes the function if the option was Some(_). Hovering over it, you can see that its type signature is:

('a => 'b, option('a)) => option('b)
('a => 'b, option('a)) => option('b)

Breaking the type signature down:

The implementation of Option.map is fairly straightforward, consisting of a single switch expression:

reason
let map = (func, option) =>
+  switch (option) {
+  | None => None
+  | Some(v) => Some(func(v))
+  };
let map = (func, option) =>
+  switch (option) {
+  | None => None
+  | Some(v) => Some(func(v))
+  };

You may be interested in browsing the many other helper functions related to option in the standard library’s Option module.

At this point, your switch expression might look like this:

re
(
+  switch (
+    celsius
+    |> float_of_string_opt
+    |> Option.map(convert)
+    |> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
+  ) {
+  | None => "error"
+  | Some(fahrenheit) => fahrenheit ++ {js|°F|js}
+  }
+)
(
+  switch (
+    celsius
+    |> float_of_string_opt
+    |> Option.map(convert)
+    |> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
+  ) {
+  | None => "error"
+  | Some(fahrenheit) => fahrenheit ++ {js|°F|js}
+  }
+)

when guard

What if we wanted to render a message of complaint when the temperature goes above 212° F (the boiling point of water) and not even bother to render the converted number? It could look like this:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    fahrenheit > 212.0
+      ? {js|Unreasonably hot🥵|js}
+      : Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    fahrenheit > 212.0
+      ? {js|Unreasonably hot🥵|js}
+      : Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)

This works, but OCaml gives you a construct that allows you to do the float comparison without using a nested ternary expression:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)

The when guard allows you to add extra conditions to a switch expression branch, keeping nesting of conditionals to a minimum and making your code more readable.

Hooray! Our Celsius converter is finally complete. Later, we’ll see how to create a component that can convert back and forth between Celsius and Fahrenheit. But first, we’ll explore Dune, the build system used by Melange.

Exercises

1. If you enter a space in the input, it’ll unintuitively produce a Fahrenheit value of 32.00 degrees (because float_of_string_opt(" ") == Some(0.)). Handle this case correctly by showing “? °F” instead. Hint: Use the String.trim function.

2. Add another branch with a when guard that renders “Unreasonably cold🥶” if the temperature is less than -128.6°F (the lowest temperature ever recorded on Earth).

3. Use Js.Float.fromString instead of float_of_string_opt to parse a string to float. Hint: Use Js.Float.isNaN.

Overview

Solutions

1. To prevent a space from producing 32.00 degrees Fahrenheit, just add a call to String.trim in your render logic:

re
(
+  String.trim(celsius) == ""
+    ? {js|?°F|js}
+    : (
+      switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+      | None => "error"
+      | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+      | Some(fahrenheit) =>
+        Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+      }
+    )
+)
(
+  String.trim(celsius) == ""
+    ? {js|?°F|js}
+    : (
+      switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+      | None => "error"
+      | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+      | Some(fahrenheit) =>
+        Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+      }
+    )
+)

2. To render “Unreasonably cold” when the temperature is less than -128.6°F, you can add another Some(fahrenheit) branch with a when guard:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)

3. To use Js.Float.fromString instead of float_of_string_opt, you can define a new helper function that takes a string and returns option:

re
let floatFromString = text => {
+  let value = Js.Float.fromString(text);
+  Js.Float.isNaN(value) ? None : Some(value);
+};
let floatFromString = text => {
+  let value = Js.Float.fromString(text);
+  Js.Float.isNaN(value) ? None : Some(value);
+};

Then substitute float_of_string_opt with floatFromString in your switch expression:

re
(
+  switch (celsius |> floatFromString |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> floatFromString |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)

Source code for this chapter can be found in the Melange for React Developers repo.

`,48),e=[p];function t(c,r,y,E,i,F){return n(),a("div",null,e)}const h=s(o,[["render",t]]);export{D as __pageData,h as default}; diff --git a/assets/celsius-converter-option_index.md.df50f66c.lean.js b/assets/celsius-converter-option_index.md.df50f66c.lean.js new file mode 100644 index 00000000..e085f3af --- /dev/null +++ b/assets/celsius-converter-option_index.md.df50f66c.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const D=JSON.parse('{"title":"Celsius Converter using Option","description":"","frontmatter":{},"headers":[],"relativePath":"celsius-converter-option/index.md","filePath":"celsius-converter-option/index.md"}'),o={name:"celsius-converter-option/index.md"},p=l("",48),e=[p];function t(c,r,y,E,i,F){return n(),a("div",null,e)}const h=s(o,[["render",t]]);export{D as __pageData,h as default}; diff --git a/assets/chunks/@localSearchIndexroot.ae053162.js b/assets/chunks/@localSearchIndexroot.ae053162.js new file mode 100644 index 00000000..eb9b8f24 --- /dev/null +++ b/assets/chunks/@localSearchIndexroot.ae053162.js @@ -0,0 +1 @@ +const e='{"documentCount":78,"nextId":78,"documentIds":{"0":"/README.html#melange-for-react-developers-book","1":"/README.html#installation","2":"/README.html#commands","3":"/celsius-converter-exception/#celsius-converter","4":"/celsius-converter-exception/#wrap-functions-that-return-js-t","5":"/celsius-converter-exception/#apply-pipe-last","6":"/celsius-converter-exception/#string-concatenation","7":"/celsius-converter-exception/#catch-exception-with-switch","8":"/celsius-converter-exception/#ternary-expression","9":"/celsius-converter-exception/#if-else-expression","10":"/celsius-converter-exception/#labeled-argument","11":"/celsius-converter-exception/#partial-application","12":"/celsius-converter-exception/#exercises","13":"/celsius-converter-exception/#overview","14":"/celsius-converter-exception/#solutions","15":"/celsius-converter-option/#celsius-converter-using-option","16":"/celsius-converter-option/#float-of-string-opt","17":"/celsius-converter-option/#option-map","18":"/celsius-converter-option/#when-guard","19":"/celsius-converter-option/#exercises","20":"/celsius-converter-option/#overview","21":"/celsius-converter-option/#solutions","22":"/counter/#counter","23":"/counter/#components-are-modules","24":"/counter/#the-make-function","25":"/counter/#wrap-strings-with-react-string","26":"/counter/#using-the-app-component","27":"/counter/#the-counter-component","28":"/counter/#the-pipe-last-operator","29":"/counter/#basic-styling","30":"/counter/#exercises","31":"/counter/#overview","32":"/counter/#solutions","33":"/installation/#installation","34":"/installation/#prerequisites","35":"/installation/#opam","36":"/installation/#download-and-run-the-starter-project","37":"/installation/#visual-studio-code-extension","38":"/intro-to-dune/#introduction-to-dune","39":"/intro-to-dune/#dune-project-file","40":"/intro-to-dune/#dune-files","41":"/intro-to-dune/#melange-emit-stanza","42":"/intro-to-dune/#counter-app-directory","43":"/intro-to-dune/#why-makefile","44":"/intro-to-dune/#anatomy-of-makefile","45":"/intro-to-dune/#root-directory-makefile","46":"/intro-to-dune/#cleanup","47":"/intro-to-dune/#rationale-for-monorepo-structure","48":"/intro-to-dune/#exercises","49":"/intro-to-dune/#overview","50":"/intro-to-dune/#solutions","51":"/intro/#melange-for-react-developers","52":"/intro/#motivation","53":"/intro/#audience","54":"/intro/#chapters-and-topics","55":"/numeric-types/#numeric-types","56":"/numeric-types/#melange-playground","57":"/numeric-types/#sharing-code-snippets","58":"/numeric-types/#comparison-operators","59":"/numeric-types/#arithmetic-operators","60":"/numeric-types/#they-re-just-number","61":"/numeric-types/#widgets-in-the-playground","62":"/numeric-types/#exercises","63":"/numeric-types/#overview","64":"/numeric-types/#solutions","65":"/order-confirmation/#order-confirmation","66":"/order-confirmation/#variant-type-item-t","67":"/order-confirmation/#wildcard-in-switch-expressions","68":"/order-confirmation/#a-fun-syntax-for-switch","69":"/order-confirmation/#item-make","70":"/order-confirmation/#order-component","71":"/order-confirmation/#react-array","72":"/order-confirmation/#index-re","73":"/order-confirmation/#js-array-mapi","74":"/order-confirmation/#exercises","75":"/order-confirmation/#overview","76":"/order-confirmation/#solutions","77":"/todo.html#content-not-yet-unavailable"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[5,1,1],"1":[1,5,4],"2":[1,5,11],"3":[2,1,121],"4":[6,2,106],"5":[6,2,52],"6":[4,2,44],"7":[4,2,73],"8":[2,2,66],"9":[3,2,98],"10":[2,2,89],"11":[2,2,110],"12":[1,2,106],"13":[1,2,77],"14":[1,2,147],"15":[4,1,112],"16":[4,4,151],"17":[2,4,126],"18":[2,4,118],"19":[1,4,71],"20":[1,4,43],"21":[1,4,106],"22":[1,1,119],"23":[3,1,49],"24":[3,1,55],"25":[5,1,35],"26":[4,1,77],"27":[3,1,84],"28":[4,1,55],"29":[2,1,90],"30":[1,1,45],"31":[1,1,56],"32":[1,1,146],"33":[1,1,1],"34":[1,1,43],"35":[1,1,70],"36":[6,1,79],"37":[4,1,61],"38":[3,1,68],"39":[3,3,126],"40":[2,3,170],"41":[3,3,112],"42":[3,3,167],"43":[2,3,43],"44":[3,3,89],"45":[3,3,101],"46":[1,3,35],"47":[4,3,94],"48":[1,3,59],"49":[1,3,68],"50":[1,3,150],"51":[4,1,8],"52":[1,4,41],"53":[1,4,66],"54":[3,4,95],"55":[2,1,54],"56":[2,2,119],"57":[3,2,52],"58":[2,2,97],"59":[2,2,69],"60":[4,2,41],"61":[4,2,141],"62":[1,2,72],"63":[1,2,74],"64":[1,2,102],"65":[2,1,81],"66":[4,2,117],"67":[4,2,86],"68":[5,2,59],"69":[2,2,63],"70":[2,2,97],"71":[2,2,148],"72":[2,2,57],"73":[3,2,124],"74":[1,2,70],"75":[1,2,96],"76":[1,2,218],"77":[4,1,19]},"averageFieldLength":[2.4487179487179485,2.1538461538461537,82.62820512820512],"storedFields":{"0":{"title":"Melange for React Developers Book","titles":[]},"1":{"title":"Installation","titles":["Melange for React Developers Book"]},"2":{"title":"Commands","titles":["Melange for React Developers Book"]},"3":{"title":"Celsius Converter","titles":[]},"4":{"title":"Wrap functions that return Js.t","titles":["Celsius Converter"]},"5":{"title":"Apply pipe last (|>)","titles":["Celsius Converter"]},"6":{"title":"String concatenation (++)","titles":["Celsius Converter"]},"7":{"title":"Catch exception with switch","titles":["Celsius Converter"]},"8":{"title":"Ternary expression","titles":["Celsius Converter"]},"9":{"title":"If-else expression","titles":["Celsius Converter"]},"10":{"title":"Labeled argument","titles":["Celsius Converter"]},"11":{"title":"Partial application","titles":["Celsius Converter"]},"12":{"title":"Exercises","titles":["Celsius Converter"]},"13":{"title":"Overview","titles":["Celsius Converter"]},"14":{"title":"Solutions","titles":["Celsius Converter"]},"15":{"title":"Celsius Converter using Option","titles":[]},"16":{"title":"float_of_string_opt","titles":["Celsius Converter using Option"]},"17":{"title":"Option.map","titles":["Celsius Converter using Option"]},"18":{"title":"when guard","titles":["Celsius Converter using Option"]},"19":{"title":"Exercises","titles":["Celsius Converter using Option"]},"20":{"title":"Overview","titles":["Celsius Converter using Option"]},"21":{"title":"Solutions","titles":["Celsius Converter using Option"]},"22":{"title":"Counter","titles":[]},"23":{"title":"Components are modules","titles":["Counter"]},"24":{"title":"The make function","titles":["Counter"]},"25":{"title":"Wrap strings with React.string","titles":["Counter"]},"26":{"title":"Using the App component","titles":["Counter"]},"27":{"title":"The Counter component","titles":["Counter"]},"28":{"title":"The pipe last operator","titles":["Counter"]},"29":{"title":"Basic styling","titles":["Counter"]},"30":{"title":"Exercises","titles":["Counter"]},"31":{"title":"Overview","titles":["Counter"]},"32":{"title":"Solutions","titles":["Counter"]},"33":{"title":"Installation","titles":[]},"34":{"title":"Prerequisites","titles":["Installation"]},"35":{"title":"Opam","titles":["Installation"]},"36":{"title":"Download and run the starter project","titles":["Installation"]},"37":{"title":"Visual Studio Code Extension","titles":["Installation"]},"38":{"title":"Introduction to Dune","titles":[]},"39":{"title":"dune-project file","titles":["Introduction to Dune"]},"40":{"title":"dune files","titles":["Introduction to Dune"]},"41":{"title":"melange.emit stanza","titles":["Introduction to Dune"]},"42":{"title":"Counter app directory","titles":["Introduction to Dune"]},"43":{"title":"Why Makefile","titles":["Introduction to Dune"]},"44":{"title":"Anatomy of Makefile","titles":["Introduction to Dune"]},"45":{"title":"Root directory Makefile","titles":["Introduction to Dune"]},"46":{"title":"Cleanup","titles":["Introduction to Dune"]},"47":{"title":"Rationale for monorepo structure","titles":["Introduction to Dune"]},"48":{"title":"Exercises","titles":["Introduction to Dune"]},"49":{"title":"Overview","titles":["Introduction to Dune"]},"50":{"title":"Solutions","titles":["Introduction to Dune"]},"51":{"title":"Melange for React Developers","titles":[]},"52":{"title":"Motivation","titles":["Melange for React Developers"]},"53":{"title":"Audience","titles":["Melange for React Developers"]},"54":{"title":"Chapters and topics","titles":["Melange for React Developers"]},"55":{"title":"Numeric Types","titles":[]},"56":{"title":"Melange Playground","titles":["Numeric Types"]},"57":{"title":"Sharing code snippets","titles":["Numeric Types"]},"58":{"title":"Comparison operators","titles":["Numeric Types"]},"59":{"title":"Arithmetic operators","titles":["Numeric Types"]},"60":{"title":"They’re just Number","titles":["Numeric Types"]},"61":{"title":"Widgets in the playground","titles":["Numeric Types"]},"62":{"title":"Exercises","titles":["Numeric Types"]},"63":{"title":"Overview","titles":["Numeric Types"]},"64":{"title":"Solutions","titles":["Numeric Types"]},"65":{"title":"Order Confirmation","titles":[]},"66":{"title":"Variant type Item.t","titles":["Order Confirmation"]},"67":{"title":"Wildcard in switch expressions","titles":["Order Confirmation"]},"68":{"title":"A fun syntax for switch","titles":["Order Confirmation"]},"69":{"title":"Item.make","titles":["Order Confirmation"]},"70":{"title":"Order component","titles":["Order Confirmation"]},"71":{"title":"React.array","titles":["Order Confirmation"]},"72":{"title":"Index.re","titles":["Order Confirmation"]},"73":{"title":"Js.Array.mapi","titles":["Order Confirmation"]},"74":{"title":"Exercises","titles":["Order Confirmation"]},"75":{"title":"Overview","titles":["Order Confirmation"]},"76":{"title":"Solutions","titles":["Order Confirmation"]},"77":{"title":"Content not yet unavailable","titles":[]}},"dirtCount":0,"index":[["🍲",{"2":{"76":1}}],["🥫",{"2":{"76":1}}],["^^^^",{"2":{"50":2}}],["^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",{"2":{"71":2}}],["^^^^^^^^^^^",{"2":{"32":2}}],["\\tnpx",{"2":{"45":2}}],["\\tapp=counter",{"2":{"42":2,"44":2}}],["└─",{"2":{"42":2,"65":2}}],["├─",{"2":{"42":6,"65":6}}],["`preprocess`",{"2":{"40":2,"42":2}}],["`",{"2":{"40":6,"42":6}}],["`target`",{"2":{"40":2,"42":2}}],["`melange",{"2":{"40":4,"42":4}}],["`dune`",{"2":{"40":2}}],["`dirs`",{"2":{"40":2}}],["$",{"2":{"35":2,"45":8}}],["66",{"2":{"58":2,"59":6}}],["6",{"2":{"21":4,"50":2,"58":2,"59":6,"71":2}}],["6°f",{"2":{"19":1,"21":1}}],["8080",{"2":{"22":1,"36":1,"45":1}}],["8",{"2":{"16":2,"32":2,"39":2}}],["keys",{"2":{"76":3}}],["keystrokes",{"2":{"61":2}}],["key=",{"2":{"73":2,"76":2}}],["key",{"2":{"22":1,"50":1,"73":4}}],["keeping",{"2":{"18":1}}],["keep",{"2":{"15":1,"39":1}}],["knowledge",{"2":{"53":1}}],["known",{"2":{"39":1}}],["know",{"2":{"12":1,"23":1,"27":1,"34":1,"50":1,"53":2}}],["knows",{"2":{"3":1}}],["↩︎",{"2":{"14":1,"32":1,"50":2,"54":1,"76":5}}],["â°c",{"2":{"14":1}}],["x",{"2":{"12":2,"71":4}}],["44",{"2":{"58":2}}],["42l",{"2":{"64":2}}],["42",{"2":{"50":3,"55":8,"56":19,"58":4,"59":4,"60":4,"62":2}}],["4",{"2":{"12":1,"14":1,"58":2,"73":1}}],["7",{"2":{"12":2}}],["33",{"2":{"58":2}}],["3d",{"2":{"57":2}}],["39",{"2":{"17":8,"26":2,"40":4,"42":4,"61":2,"72":2,"73":8}}],["31",{"2":{"16":2}}],["30",{"2":{"16":2}}],["3",{"2":{"12":1,"14":1,"19":1,"21":1,"30":1,"32":5,"39":2,"48":1,"50":1,"58":2,"62":1,"64":1,"71":1,"74":1,"76":1}}],["32",{"2":{"3":2,"4":2,"15":2,"16":4,"19":1,"21":1}}],["°c",{"2":{"12":1,"14":1}}],["°f",{"2":{"6":1,"8":1,"19":1}}],["°f|js",{"2":{"3":2,"4":2,"8":2,"9":2,"10":2,"11":2,"15":2,"16":2,"18":4,"21":4}}],["~items",{"2":{"70":3,"76":2}}],["~item",{"2":{"69":3,"76":2}}],["~textalign=",{"2":{"61":2}}],["~minwidth=",{"2":{"61":2}}],["~borderradius=",{"2":{"61":2}}],["~border=",{"2":{"61":2}}],["~alignitems=",{"2":{"61":2}}],["~fontsize=",{"2":{"61":4}}],["~",{"2":{"35":2}}],["~gridgap=",{"2":{"29":2,"61":4,"64":2}}],["~display=",{"2":{"29":2,"61":4,"64":2}}],["~digits=2",{"2":{"10":2,"11":3,"15":2,"16":2,"17":6,"18":4,"21":6,"69":2,"70":2,"71":2,"74":1,"76":2}}],["~padding=",{"2":{"29":2,"61":6,"64":2}}],["~label=value",{"2":{"10":1}}],["2em",{"2":{"61":4}}],["27",{"2":{"32":4}}],["29",{"2":{"16":2}}],["25",{"2":{"16":2}}],["24",{"2":{"16":2}}],["23",{"2":{"16":2}}],["22",{"2":{"16":2}}],["2",{"2":{"10":1,"12":3,"14":1,"19":1,"21":1,"30":1,"32":1,"48":1,"50":4,"56":2,"62":1,"64":1,"66":1,"74":1,"76":1}}],["212",{"2":{"18":4,"21":6}}],["212°",{"2":{"18":1}}],["21",{"2":{"10":1,"16":4}}],["query",{"2":{"57":1}}],["queryselector",{"2":{"26":3,"42":2,"61":2,"72":2}}],["quite",{"2":{"9":1,"52":1}}],["quoted",{"2":{"14":1}}],["quot",{"2":{"3":4,"4":4,"7":8,"8":8,"9":8,"10":8,"11":8,"12":2,"14":2,"15":12,"16":12,"17":4,"18":8,"19":2,"21":16,"22":4,"26":10,"27":8,"29":20,"32":4,"35":4,"37":16,"42":8,"50":6,"60":8,"61":80,"64":20,"70":4,"71":20,"72":12,"73":8,"76":8}}],["y",{"2":{"35":1}}],["yet",{"0":{"77":1},"2":{"9":1}}],["yields",{"2":{"9":1}}],["yourself",{"2":{"55":1}}],["yourpackage",{"2":{"46":1}}],["your",{"2":{"12":1,"15":3,"17":1,"18":1,"20":1,"21":2,"22":1,"29":1,"32":3,"35":1,"36":1,"37":1,"38":1,"39":3,"40":1,"42":1,"45":2,"47":1,"49":2,"53":1,"57":2,"58":1,"61":1,"62":1,"63":2,"66":2,"67":1,"68":1,"72":1,"73":1,"74":1,"75":3,"76":2}}],["you",{"2":{"7":1,"8":1,"9":5,"11":2,"12":2,"13":2,"15":3,"16":7,"17":2,"18":3,"19":1,"20":2,"21":2,"22":4,"23":1,"24":1,"25":2,"26":1,"27":1,"29":1,"30":2,"32":6,"34":2,"35":3,"36":2,"37":2,"38":2,"39":4,"40":2,"41":1,"42":3,"43":1,"44":1,"45":2,"46":2,"47":4,"48":3,"49":3,"50":2,"53":3,"55":2,"56":4,"57":1,"58":4,"59":3,"61":1,"62":1,"64":1,"65":3,"66":4,"67":5,"68":1,"71":3,"73":4,"75":5,"76":8,"77":1}}],["row",{"2":{"69":1}}],["root",{"0":{"45":1},"2":{"22":1,"26":9,"29":1,"39":1,"40":1,"42":9,"44":1,"45":2,"46":2,"47":1,"61":8,"72":8}}],["rule",{"2":{"44":2,"45":2,"48":1,"50":1}}],["rules",{"2":{"40":4,"42":4,"49":1,"76":1}}],["rundown",{"2":{"60":1}}],["runtime",{"2":{"30":1}}],["running",{"2":{"22":1,"34":1,"35":1,"36":2,"44":1,"56":1,"71":1}}],["run",{"0":{"36":1},"2":{"12":1,"22":2,"31":1,"35":1,"41":2,"44":1,"45":4,"49":1,"72":1}}],["rationale",{"0":{"47":1}}],["raw",{"2":{"35":2}}],["raised",{"2":{"16":1}}],["right",{"2":{"8":1,"28":1,"30":1,"56":2}}],["requested",{"2":{"77":1}}],["requires",{"2":{"70":1}}],["reitems",{"2":{"73":1}}],["retype",{"2":{"66":1,"70":1,"76":2}}],["returns",{"2":{"16":1,"17":1,"21":1,"22":1,"24":1,"26":3,"71":1}}],["return",{"0":{"4":1},"2":{"4":2,"9":1,"13":1,"14":1,"17":1,"20":2,"66":1}}],["renaming",{"2":{"32":1}}],["rename",{"2":{"30":1,"74":1}}],["rendering",{"2":{"76":1}}],["rendered",{"2":{"14":1,"74":1}}],["renders",{"2":{"8":2,"19":1,"22":1,"42":1,"69":1}}],["render",{"2":{"5":1,"18":2,"21":2,"26":3,"42":3,"61":4,"63":1,"69":2,"70":1,"72":3}}],["reduce",{"2":{"24":1,"70":5,"71":2,"75":2,"76":2}}],["remember",{"2":{"32":1,"65":1}}],["remedy",{"2":{"7":1}}],["removing",{"2":{"32":1,"75":1}}],["removed",{"2":{"66":1}}],["remove",{"2":{"30":1}}],["remodule",{"2":{"22":1,"27":1,"42":1,"61":2,"72":1}}],["remind",{"2":{"20":1}}],["referred",{"2":{"66":1}}],["refer",{"2":{"60":1}}],["references",{"2":{"76":1}}],["referenced",{"2":{"41":1,"76":1}}],["reference",{"2":{"39":1,"40":1}}],["refers",{"2":{"3":2}}],["refuse",{"2":{"16":1}}],["refactor",{"2":{"16":1,"71":1}}],["represented",{"2":{"64":1}}],["represent",{"2":{"64":1}}],["representation",{"2":{"62":1}}],["replacing",{"2":{"50":1,"54":1}}],["replace",{"2":{"48":1}}],["replaced",{"2":{"11":1}}],["repeatedly",{"2":{"74":1}}],["repeat",{"2":{"48":1}}],["repo",{"2":{"14":1,"21":1,"32":1,"47":1,"50":1,"64":1,"76":1}}],["recall",{"2":{"76":1}}],["recommends",{"2":{"47":1}}],["recorded",{"2":{"19":1}}],["recipe",{"2":{"44":1,"45":1,"48":2,"50":1}}],["recent",{"2":{"34":1}}],["receiving",{"2":{"10":1}}],["recycled",{"2":{"14":1}}],["rewriting",{"2":{"14":1}}],["rewrite",{"2":{"9":1,"11":1,"12":1,"67":1,"68":1}}],["resrc",{"2":{"65":1}}],["restaurant",{"2":{"65":1,"76":1}}],["restauranteur",{"2":{"65":1}}],["rest",{"2":{"39":1}}],["restriction",{"2":{"11":1,"58":1}}],["results",{"2":{"32":1}}],["result",{"2":{"12":1,"14":1,"32":1,"50":2,"64":4}}],["reality",{"2":{"71":1}}],["ready",{"2":{"45":1,"69":1}}],["reading",{"2":{"44":1}}],["readthedocs",{"2":{"40":2,"42":2}}],["read",{"2":{"28":1}}],["readable",{"2":{"18":1,"24":1,"62":1}}],["reasonjs",{"2":{"58":3,"59":2}}],["reasonml",{"2":{"40":2}}],["reason",{"2":{"28":1,"37":2,"40":8,"42":4,"48":1,"50":2,"54":1,"71":1,"76":1}}],["reasonably",{"2":{"16":1}}],["reasonreact",{"2":{"14":1,"22":2,"23":1,"29":2,"31":2,"40":2,"53":1,"54":2,"61":1,"63":1,"73":1,"75":1}}],["reasonlet",{"2":{"12":1,"17":1,"55":2,"56":2,"58":1,"60":1,"62":1,"64":1,"67":3}}],["reasoncelsius",{"2":{"11":2,"17":2}}],["reactdomstyle",{"2":{"29":4,"61":4,"64":2}}],["reactdom",{"2":{"26":4,"42":4,"61":4,"72":4}}],["reactevent",{"2":{"3":5,"4":3,"15":2}}],["react",{"0":{"0":1,"25":1,"51":1,"71":1},"1":{"1":1,"2":1,"52":1,"53":1,"54":1},"2":{"3":8,"4":8,"5":5,"6":4,"7":8,"8":4,"9":4,"10":4,"11":4,"14":1,"15":8,"21":1,"22":8,"24":4,"25":4,"26":3,"27":13,"28":4,"29":7,"30":1,"32":3,"36":5,"37":1,"39":2,"40":6,"42":8,"48":1,"50":4,"53":1,"61":18,"64":11,"69":6,"70":8,"71":28,"72":6,"73":2,"74":1,"75":3,"76":16}}],["relevant",{"2":{"66":1,"75":1}}],["relet",{"2":{"3":1,"4":1,"15":1,"21":1,"26":1,"66":1,"68":2,"71":2,"76":1}}],["related",{"2":{"17":1,"43":1}}],["rely",{"2":{"9":1,"14":1}}],["re",{"0":{"60":1,"72":1},"2":{"3":1,"5":1,"6":2,"7":2,"8":1,"9":1,"10":1,"11":1,"12":1,"14":1,"15":1,"16":3,"17":1,"18":2,"21":3,"22":2,"27":2,"29":1,"30":1,"32":4,"36":2,"39":1,"40":2,"41":1,"42":8,"43":1,"44":2,"45":1,"46":1,"47":1,"49":2,"50":3,"57":1,"61":1,"64":2,"65":4,"66":1,"67":1,"69":2,"70":1,"71":2,"72":1,"76":4}}],["violates",{"2":{"76":1}}],["via",{"2":{"63":1,"70":1}}],["visual",{"0":{"37":1},"2":{"34":1,"37":2}}],["v2",{"2":{"40":2,"57":1}}],["variants",{"2":{"70":1}}],["variant",{"0":{"66":1},"2":{"66":2,"74":1,"75":2,"76":1}}],["variables",{"2":{"32":1,"37":1,"56":2}}],["variable",{"2":{"30":1,"32":2,"44":1,"45":1,"65":1}}],["var",{"2":{"32":2,"56":4}}],["values",{"2":{"13":1,"14":2,"58":2,"62":1,"63":1,"64":2}}],["value=celsius",{"2":{"3":2,"4":2,"12":2,"14":2,"15":2}}],["value",{"2":{"3":4,"4":4,"5":1,"6":1,"8":1,"9":2,"10":5,"14":2,"15":2,"16":2,"17":5,"19":1,"21":6,"31":1,"32":2,"41":2,"45":1,"50":2,"62":1,"65":1,"70":1,"74":1,"76":4}}],["ve",{"2":{"22":1,"29":1,"38":1,"39":2,"42":1,"59":1,"65":1,"73":1}}],["verify",{"2":{"35":1,"37":1}}],["versionopam",{"2":{"35":1}}],["version",{"2":{"16":1,"34":1,"35":1,"39":4,"49":2,"67":1}}],["very",{"2":{"5":1,"9":1,"17":1,"20":1,"32":1,"47":1,"50":1,"67":1}}],["v",{"2":{"17":4,"27":8,"29":8,"61":16,"64":8}}],["url",{"2":{"57":1,"63":1}}],["uppercase",{"2":{"76":1}}],["updating",{"2":{"66":1}}],["update",{"2":{"5":1,"61":1,"65":1,"74":1}}],["up",{"2":{"17":1,"41":1,"53":1,"65":1,"68":1,"70":1,"76":1}}],["unavailable",{"0":{"77":1}}],["unstyled",{"2":{"76":1}}],["unsigned",{"2":{"64":1}}],["underlying",{"2":{"71":1}}],["underneath",{"2":{"60":1}}],["under",{"2":{"44":1}}],["underscores",{"2":{"62":1}}],["underscore",{"2":{"7":1,"32":1,"67":1}}],["unbound",{"2":{"32":2,"50":2}}],["unless",{"2":{"32":1,"58":1,"75":1}}],["unlike",{"2":{"9":1,"13":1,"25":1,"29":1,"58":1,"73":1}}],["unused",{"2":{"32":4}}],["unreasonably",{"2":{"19":1,"21":1}}],["unexpected",{"2":{"15":1}}],["union",{"2":{"76":1}}],["unique",{"2":{"73":2}}],["unix",{"2":{"34":1}}],["unintuitively",{"2":{"19":1}}],["unicode",{"2":{"14":1}}],["unit",{"2":{"6":1,"24":1}}],["usage",{"2":{"43":1}}],["usable",{"2":{"32":1}}],["us",{"2":{"5":1,"11":1,"41":1}}],["uses",{"2":{"27":1,"28":1,"52":1,"59":1,"64":1}}],["usestate",{"2":{"3":2,"4":2,"14":1,"15":2,"27":3,"61":2,"64":2}}],["useful",{"2":{"20":1,"28":1,"38":1,"75":1}}],["users",{"2":{"34":1}}],["user",{"2":{"6":1,"8":1,"37":1}}],["used",{"2":{"4":1,"9":1,"13":1,"18":1,"32":1,"39":2,"40":2,"42":2,"44":1,"49":1,"74":2}}],["use",{"2":{"3":1,"4":1,"9":2,"12":3,"13":2,"14":1,"16":1,"17":1,"19":3,"20":1,"21":1,"26":1,"32":1,"34":1,"39":5,"40":4,"41":1,"42":2,"45":1,"47":3,"49":1,"54":1,"61":4,"62":2,"68":2,"73":1,"75":1,"76":2}}],["using",{"0":{"15":1,"26":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1,"21":1},"2":{"3":1,"4":1,"6":1,"7":1,"10":2,"11":2,"13":2,"14":5,"17":1,"18":1,"22":1,"29":1,"39":7,"40":4,"42":3,"43":1,"49":3,"53":1,"54":1,"64":1,"65":1,"68":3,"70":1,"74":1,"75":1,"76":1}}],["|sandwich",{"2":{"72":2}}],["|",{"0":{"5":1},"2":{"5":9,"6":8,"7":25,"8":12,"9":12,"10":10,"11":23,"12":1,"15":13,"16":37,"17":26,"18":18,"21":34,"26":4,"28":4,"29":4,"30":1,"32":3,"42":4,"50":2,"61":12,"64":4,"66":9,"67":10,"68":8,"69":10,"70":10,"71":24,"72":4,"73":4,"74":2,"76":42}}],["|js",{"2":{"3":2,"4":2,"5":2,"6":2,"7":4,"8":2,"9":2,"10":2,"11":2,"12":1,"15":2}}],["etc",{"2":{"76":1}}],["equivalent",{"2":{"68":1,"76":1}}],["empty",{"2":{"65":1}}],["empowered",{"2":{"61":1}}],["emojis",{"2":{"76":1}}],["emoji",{"2":{"65":1,"66":2,"76":1}}],["emit",{"0":{"41":1},"2":{"40":4,"41":3,"42":5,"46":1,"47":3,"48":1,"49":1}}],["emit`",{"2":{"40":4,"42":4}}],["efficient",{"2":{"53":1}}],["effectively",{"2":{"69":1}}],["effect",{"2":{"22":1,"44":1}}],["ecosystems",{"2":{"52":1}}],["ecosystem",{"2":{"52":1}}],["es6",{"2":{"40":4,"42":4}}],["editors",{"2":{"34":1,"50":1}}],["editor",{"2":{"34":1,"37":4,"56":1,"57":1}}],["either",{"2":{"31":1}}],["each",{"2":{"38":1,"39":1,"47":2,"52":1,"70":1,"73":2}}],["easy",{"2":{"31":1}}],["easier",{"2":{"24":1}}],["earth",{"2":{"19":1}}],["e",{"2":{"10":1,"26":1,"64":1,"75":1}}],["elemarray",{"2":{"71":10}}],["elements",{"2":{"71":1,"75":1,"76":1}}],["elementfile",{"2":{"71":1}}],["element",{"2":{"5":1,"22":1,"24":2,"25":2,"26":8,"28":1,"29":1,"42":2,"61":2,"71":12,"72":2,"73":2,"75":1,"76":1}}],["else",{"0":{"9":1},"2":{"9":6,"13":2,"16":1,"40":1,"54":1,"74":1}}],["errors",{"2":{"30":1,"48":1}}],["error",{"2":{"7":4,"8":4,"9":3,"10":2,"11":2,"12":1,"15":2,"16":7,"17":2,"18":4,"20":1,"21":6,"26":3,"32":8,"39":2,"42":2,"50":4,"56":3,"58":1,"63":1,"71":4,"72":2}}],["existing",{"2":{"53":1,"65":1}}],["excellent",{"2":{"57":1}}],["exceptions",{"2":{"11":1,"13":1,"15":1,"20":1}}],["exception",{"0":{"7":1},"2":{"7":9,"8":2,"9":2,"10":2,"11":2,"15":4,"16":1,"54":2}}],["exclude",{"2":{"40":2,"49":1}}],["extensions",{"2":{"37":1}}],["extension",{"0":{"37":1},"2":{"37":2,"39":2}}],["extra",{"2":{"18":1}}],["exhaustive",{"2":{"16":2,"32":2}}],["exactly",{"2":{"16":1,"25":1}}],["examples",{"2":{"59":1}}],["example",{"2":{"3":1,"4":1,"16":2,"23":1,"32":2,"40":1,"41":1,"42":2,"49":1,"55":1,"57":1,"71":1}}],["export",{"2":{"56":2}}],["explicitly",{"2":{"61":1,"67":1}}],["explain",{"2":{"43":1}}],["explore",{"2":{"18":1,"54":1}}],["express",{"2":{"26":1}}],["expressive",{"2":{"20":1}}],["expressions",{"0":{"67":1},"2":{"9":1,"13":4,"32":1,"39":2,"67":1}}],["expression",{"0":{"8":1,"9":1},"2":{"7":1,"8":2,"9":3,"11":2,"12":1,"14":1,"15":1,"16":2,"17":2,"18":2,"20":2,"21":1,"26":1,"30":1,"39":1,"54":2,"56":4,"58":4,"66":1,"68":2,"71":4,"75":2}}],["experience",{"2":{"16":1}}],["expected",{"2":{"56":2,"58":2,"71":3}}],["expects",{"2":{"50":1,"71":1}}],["expect",{"2":{"14":1,"58":1,"63":1,"74":1,"76":1}}],["executables",{"2":{"40":1}}],["executed",{"2":{"44":1}}],["execute",{"2":{"7":1}}],["exercises",{"0":{"12":1,"19":1,"30":1,"48":1,"62":1,"74":1}}],["enums",{"2":{"76":1}}],["enough",{"2":{"64":1}}],["end",{"2":{"41":1,"59":1,"63":1}}],["entire",{"2":{"68":1,"75":1}}],["entry",{"2":{"41":3,"45":4}}],["entered",{"2":{"15":1}}],["enter",{"2":{"7":1,"8":1,"10":1,"19":1}}],["en",{"2":{"40":4,"42":2}}],["enable",{"2":{"37":1,"39":1,"42":2}}],["enables",{"2":{"31":1}}],["environment",{"2":{"44":1,"45":1,"56":1,"65":1}}],["env",{"2":{"35":2}}],["encoding",{"2":{"39":1}}],["encouraged",{"2":{"34":1}}],["enclosed",{"2":{"4":1}}],["ensures",{"2":{"4":1}}],["eval",{"2":{"35":2}}],["every",{"2":{"41":1,"47":1,"48":1,"50":1}}],["everything",{"2":{"36":1,"76":1}}],["ever",{"2":{"19":1}}],["even",{"2":{"12":1,"16":1,"18":1}}],["event",{"2":{"3":1,"14":2}}],["evt",{"2":{"3":5,"4":10,"12":4,"14":7,"15":8,"27":4,"29":4,"30":2,"32":4,"61":8,"64":4}}],["nifty",{"2":{"56":1}}],["nice",{"2":{"9":1}}],["numeric",{"0":{"55":1},"1":{"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":1},"2":{"54":1,"55":1}}],["numbers",{"2":{"61":1,"64":1}}],["number",{"0":{"60":1},"2":{"10":1,"16":1,"18":1,"28":1,"50":1,"54":1,"60":5,"61":4,"62":1,"63":1,"64":1}}],["npm",{"2":{"41":1,"43":1,"45":1}}],["native",{"2":{"14":1}}],["names",{"2":{"76":1}}],["name",{"2":{"13":1,"23":2,"27":2,"32":1,"39":5,"44":1,"49":1,"76":1}}],["named",{"2":{"10":1,"23":1,"66":1,"69":1,"70":1,"75":1}}],["node",{"2":{"26":6,"30":1,"34":1,"40":4,"41":2,"42":4,"72":4}}],["normal",{"2":{"25":1}}],["no",{"2":{"14":3,"16":1,"47":1,"56":1,"58":1,"76":1}}],["noneerror",{"2":{"32":1}}],["nonefile",{"2":{"16":1}}],["none",{"2":{"16":7,"17":6,"18":4,"21":8,"26":4,"30":1,"31":1,"32":3,"42":2,"61":2,"72":2}}],["non",{"2":{"14":1}}],["now",{"2":{"8":1,"11":1,"12":1,"14":1,"22":1,"23":1,"24":1,"27":1,"30":1,"32":1,"45":1,"56":1,"61":2,"65":1,"67":1,"69":1,"76":1}}],["notice",{"2":{"55":1,"59":1}}],["noticed",{"2":{"11":1,"48":1,"71":1}}],["notable",{"2":{"23":1}}],["not",{"0":{"77":1},"2":{"10":1,"14":1,"16":5,"18":1,"32":4,"40":1,"44":2,"52":1,"53":1,"56":2,"67":1,"73":1}}],["note",{"2":{"4":1,"14":1,"27":1,"39":1,"40":1,"41":1,"55":1,"56":1,"61":1,"62":1,"69":1,"70":1}}],["nothing",{"2":{"3":1}}],["necessary",{"2":{"39":1,"44":1}}],["nesting",{"2":{"18":1,"20":1}}],["nested",{"2":{"18":1}}],["next",{"2":{"11":1,"15":1,"61":1,"73":1}}],["needed",{"2":{"75":1}}],["need",{"2":{"4":1,"23":1,"24":1,"27":1,"32":1,"35":1,"40":2,"41":1,"42":2,"45":1,"46":1,"50":1,"53":1,"66":1,"69":1,"71":1}}],["newbie",{"2":{"32":1}}],["newcelsius",{"2":{"3":4,"4":4,"15":4}}],["new",{"2":{"3":1,"21":1,"23":1,"27":2,"42":3,"45":2,"47":3,"61":1,"65":2,"66":1,"70":1,"72":1,"76":1}}],["personal",{"2":{"68":1}}],["period",{"2":{"59":1}}],["phony",{"2":{"42":2,"44":5,"45":2}}],["pps",{"2":{"40":2,"42":2,"50":1}}],["ppx",{"2":{"32":1,"40":8,"42":4,"48":1,"50":2}}],["please",{"2":{"77":1}}],["plugin",{"2":{"39":2,"49":1}}],["plain",{"2":{"73":1}}],["play",{"2":{"63":1,"71":1}}],["playground",{"0":{"56":1,"61":1},"2":{"12":1,"14":2,"54":3,"56":1,"57":2,"58":1,"59":1,"61":3,"62":1,"63":1,"71":1}}],["platform",{"2":{"35":1,"37":3}}],["place",{"2":{"32":1}}],["placeholder",{"2":{"17":2}}],["puked",{"2":{"76":1}}],["pure",{"2":{"56":2}}],["purposes",{"2":{"38":1}}],["public",{"2":{"50":1}}],["putting",{"2":{"11":1,"50":1}}],["put",{"2":{"6":1,"32":1,"38":1,"39":1,"40":2,"42":2,"47":1}}],["pane",{"2":{"56":2}}],["panel",{"2":{"56":2}}],["paste",{"2":{"56":1,"61":1}}],["passing",{"2":{"76":1}}],["passes",{"2":{"73":1}}],["passed",{"2":{"70":1}}],["pass",{"2":{"10":1,"14":1,"49":1}}],["page",{"2":{"36":2}}],["package",{"2":{"35":1,"45":1,"47":1,"50":1}}],["parameter",{"2":{"57":1}}],["parse",{"2":{"19":1}}],["particular",{"2":{"53":1}}],["partial",{"0":{"11":1},"2":{"11":1,"12":2,"13":1,"14":1,"16":2,"32":2,"54":1}}],["part",{"2":{"32":1}}],["parts",{"2":{"3":1,"66":1,"75":1}}],["pattern",{"2":{"16":3,"32":2,"67":1,"75":1}}],["potoffood",{"2":{"76":1}}],["potential",{"2":{"14":1}}],["pop",{"2":{"65":1}}],["points",{"2":{"36":1}}],["pointed",{"2":{"22":1}}],["point",{"2":{"17":1,"18":1}}],["power",{"2":{"16":1,"39":1}}],["possible",{"2":{"10":1,"12":2,"39":1,"40":1}}],["positional",{"2":{"10":1,"13":1}}],["polymorphic",{"2":{"3":1,"4":1,"54":1}}],["prices",{"2":{"70":1}}],["price",{"2":{"66":1,"67":2,"76":1}}],["prints",{"2":{"59":2,"60":4,"64":2}}],["primarily",{"2":{"49":1,"71":1}}],["primary",{"2":{"38":1,"66":1,"70":1}}],["precision",{"2":{"64":1}}],["press",{"2":{"50":1}}],["prefix",{"2":{"76":1}}],["prefixed",{"2":{"48":1}}],["prefer",{"2":{"20":1}}],["pretty",{"2":{"41":1}}],["preprocess",{"2":{"40":2,"41":1,"42":2,"50":1}}],["preprocessors",{"2":{"40":2,"42":2}}],["prerequisites",{"0":{"34":1}}],["preview",{"2":{"61":4}}],["previous",{"2":{"16":1,"61":1,"62":1,"65":1}}],["prevent",{"2":{"11":1,"21":1}}],["promotion",{"2":{"67":1}}],["prompt",{"2":{"35":1}}],["progress",{"2":{"51":1}}],["programs",{"2":{"61":1,"63":1}}],["programming",{"2":{"39":1,"53":1}}],["program",{"2":{"12":1,"15":1,"58":1,"62":1,"63":1,"74":1}}],["provided",{"2":{"45":1}}],["process",{"2":{"40":2}}],["profile",{"2":{"35":2}}],["prop",{"2":{"29":1,"31":1,"69":1,"70":1,"73":2}}],["props",{"2":{"10":1,"73":1,"75":1}}],["projects",{"2":{"38":1,"43":2,"47":2,"49":1,"65":1}}],["project",{"0":{"36":1,"39":1},"2":{"22":3,"36":2,"37":1,"38":1,"39":9,"40":5,"41":1,"47":4,"49":3,"50":4,"52":1}}],["producing",{"2":{"21":1}}],["produce",{"2":{"19":1,"40":2,"42":2}}],["problems",{"2":{"56":3}}],["problem",{"2":{"14":1}}],["probably",{"2":{"6":1,"59":1}}],["practice",{"2":{"9":1}}],["pipe",{"0":{"5":1,"28":1},"2":{"5":1,"12":1,"28":1,"31":1,"54":1}}],["jellobutter",{"2":{"65":1,"66":1,"67":1,"76":1}}],["just",{"0":{"60":1},"2":{"21":1,"22":1,"23":1,"24":1,"32":1,"39":1,"42":1,"43":1,"44":1,"59":1,"71":1,"76":1}}],["javascriptconsole",{"2":{"71":1}}],["javascript",{"2":{"3":1,"4":1,"9":2,"23":1,"32":1,"40":8,"41":5,"42":6,"49":1,"52":1,"53":1,"55":1,"56":1,"58":1,"60":2,"61":1,"62":1,"63":3,"64":1,"70":1,"71":2,"73":1,"75":2,"76":1}}],["jswebpack",{"2":{"41":1}}],["json",{"2":{"37":2,"45":1,"46":1,"47":1,"50":1}}],["jsx",{"2":{"22":1,"32":1,"40":6,"42":2,"50":1,"54":1,"61":1}}],["js",{"0":{"4":1,"73":1},"2":{"3":3,"10":4,"11":5,"12":7,"13":5,"14":2,"15":2,"16":2,"17":6,"18":4,"19":2,"21":11,"26":2,"34":1,"41":3,"42":2,"45":4,"50":1,"55":8,"56":8,"58":11,"59":7,"60":8,"61":2,"62":2,"64":2,"69":2,"70":9,"71":19,"72":2,"73":5,"74":1,"75":5,"76":6}}],["js|🌭|js",{"2":{"76":2}}],["js|🍔|js",{"2":{"68":2,"76":2}}],["js|🥪|js",{"2":{"68":2,"76":2}}],["js|unreasonably",{"2":{"18":4,"21":10}}],["js||js",{"2":{"14":1}}],["js|°f|js",{"2":{"6":2,"7":4,"8":2,"9":2,"10":2,"11":2,"15":2,"16":2,"17":2,"21":4}}],["js|°c",{"2":{"3":2,"4":2,"5":2,"6":2,"7":4,"8":2,"9":2,"10":2,"11":2,"12":1,"15":2}}],["js|",{"2":{"3":2,"4":2,"8":2,"9":2,"10":2,"11":2,"15":2,"16":2,"18":4,"21":4}}],["1px",{"2":{"61":2}}],["16l",{"2":{"64":2}}],["16",{"2":{"59":4}}],["15",{"2":{"56":2,"66":2,"68":2,"76":2}}],["142",{"2":{"56":1}}],["19",{"2":{"32":2}}],["1em",{"2":{"29":4,"61":10,"64":4}}],["12",{"2":{"71":6}}],["128",{"2":{"19":1,"21":5}}],["1223456",{"2":{"10":1}}],["11",{"2":{"16":2}}],["10",{"2":{"12":3,"14":1,"16":2,"66":2,"67":8,"68":2,"76":2}}],["1",{"2":{"3":2,"12":1,"14":1,"19":1,"21":1,"26":1,"27":4,"29":4,"30":1,"32":1,"39":6,"47":1,"48":1,"50":1,"53":1,"55":4,"56":9,"57":1,"61":8,"62":2,"64":3,"66":1,"74":1,"76":1}}],["glimpse",{"2":{"76":1}}],["ground",{"2":{"53":1}}],["great",{"2":{"47":1,"54":1,"63":1,"66":1,"73":1}}],["grabbing",{"2":{"36":1}}],["guess",{"2":{"59":1}}],["guide",{"2":{"53":1,"54":1}}],["guided",{"2":{"52":1}}],["guidelines",{"2":{"47":1}}],["guard",{"0":{"18":1},"2":{"18":1,"19":1,"20":1,"21":1,"54":1}}],["generated",{"2":{"56":3}}],["generate",{"2":{"40":4,"42":4,"44":1,"76":1}}],["generic",{"2":{"29":1,"31":1}}],["gets",{"2":{"50":1}}],["getvaluefromevent",{"2":{"4":5,"12":2,"14":4,"15":4}}],["get",{"2":{"3":1,"9":1,"10":1,"13":1,"16":1,"48":1,"58":1,"60":1,"71":3,"74":1}}],["github",{"2":{"36":2,"40":2}}],["githubusercontent",{"2":{"35":2}}],["git",{"2":{"34":1}}],["given",{"2":{"56":1,"66":1}}],["give",{"2":{"17":1,"41":1,"65":1}}],["gives",{"2":{"16":1,"18":1}}],["gibberish",{"2":{"14":1}}],["g",{"2":{"10":1,"64":1,"75":1}}],["go",{"2":{"22":2,"24":1,"35":1,"45":1}}],["going",{"2":{"22":1,"47":3,"70":1}}],["goes",{"2":{"18":1,"53":1}}],["got",{"2":{"11":1,"73":1}}],["gotten",{"2":{"9":1}}],["good",{"2":{"4":1,"53":1}}],["gt",{"0":{"5":1},"2":{"3":17,"4":18,"5":16,"6":14,"7":36,"8":18,"9":18,"10":16,"11":29,"12":7,"14":6,"15":30,"16":17,"17":33,"18":22,"21":42,"22":6,"24":1,"25":1,"26":6,"27":28,"28":4,"29":28,"32":4,"42":10,"58":4,"61":66,"64":32,"66":6,"67":14,"68":8,"69":24,"70":38,"71":54,"72":18,"73":12,"74":2,"76":84}}],["wunderbar",{"2":{"73":1}}],["w00t",{"2":{"61":1}}],["watch",{"2":{"22":2}}],["water",{"2":{"18":1}}],["warning",{"2":{"16":2,"32":4,"51":1,"73":3}}],["warn",{"2":{"15":1}}],["ways",{"2":{"15":1,"35":1}}],["way",{"2":{"11":1,"15":1,"28":1,"29":1,"31":1,"57":1,"58":1,"63":1,"67":1,"73":1,"76":1}}],["was",{"2":{"11":1,"14":1,"16":1,"17":1,"36":1,"56":2,"58":2,"71":2,"76":1}}],["wants",{"2":{"32":1}}],["want",{"2":{"7":1,"32":2,"35":2,"44":1,"45":1,"47":1,"61":1,"68":1,"75":1}}],["wanted",{"2":{"7":1,"18":1,"41":1}}],["world",{"2":{"36":1,"49":1}}],["worry",{"2":{"32":1}}],["work",{"2":{"51":1,"55":2,"77":1}}],["worked",{"2":{"37":1}}],["working",{"2":{"11":1}}],["works",{"2":{"9":1,"18":1,"36":1,"54":1}}],["would",{"2":{"16":1,"50":1,"55":1,"64":1,"66":2,"67":3,"74":1}}],["wouldn",{"2":{"3":1}}],["wondering",{"2":{"43":1}}],["won",{"2":{"15":1,"46":1,"54":1,"59":2}}],["wrote",{"2":{"28":1}}],["writing",{"2":{"11":1,"77":1}}],["write",{"2":{"3":1,"7":1,"12":1,"50":1,"55":1}}],["wrapped",{"2":{"26":1}}],["wrapping",{"2":{"8":1}}],["wraps",{"2":{"17":2}}],["wrap",{"0":{"4":1,"25":1},"2":{"4":1,"22":1,"25":1}}],["why",{"0":{"43":1},"2":{"43":1}}],["whole",{"2":{"39":1}}],["whose",{"2":{"31":1,"41":1,"68":1,"75":1}}],["white",{"2":{"61":2}}],["while",{"2":{"35":1,"36":2,"56":1,"76":1}}],["which",{"2":{"3":3,"7":1,"11":2,"15":2,"17":2,"28":2,"34":1,"36":1,"39":4,"40":6,"41":2,"42":3,"44":1,"45":1,"49":4,"50":1,"53":1,"54":1,"56":1,"61":1,"69":1,"70":3,"71":2,"76":1}}],["whether",{"2":{"68":1}}],["where",{"2":{"32":2,"40":2,"41":1,"47":1,"50":1,"64":1,"73":1}}],["when",{"0":{"18":1},"2":{"8":1,"9":1,"10":1,"14":1,"15":1,"17":1,"18":4,"19":1,"20":3,"21":12,"37":1,"44":1,"50":1,"54":1,"56":1,"63":1,"73":1,"75":3}}],["what",{"2":{"3":1,"6":1,"12":3,"15":1,"16":1,"18":1,"25":1,"30":3,"31":1,"32":2,"48":2,"56":1,"59":3,"62":1,"71":1}}],["website",{"2":{"65":1}}],["webpack",{"2":{"22":1,"42":1,"45":3,"50":1}}],["welcome",{"2":{"22":2}}],["well",{"2":{"10":1,"40":2,"42":2}}],["were",{"2":{"3":1,"17":1}}],["we",{"2":{"3":4,"6":2,"7":4,"8":1,"9":1,"10":5,"11":2,"13":1,"14":6,"15":2,"17":4,"18":3,"22":4,"24":1,"25":1,"26":2,"27":1,"28":1,"29":2,"31":1,"35":1,"38":1,"39":3,"41":5,"43":2,"44":3,"45":4,"47":4,"48":1,"49":1,"50":1,"52":1,"53":1,"54":2,"57":1,"61":3,"62":1,"65":1,"68":2,"69":2,"70":2,"71":5,"73":4,"74":1,"76":3,"77":1}}],["windows",{"2":{"34":2}}],["window",{"2":{"22":1}}],["wildcards",{"2":{"67":1,"75":2}}],["wildcard",{"0":{"67":1},"2":{"7":1,"67":1}}],["will",{"2":{"3":1,"7":3,"14":1,"15":1,"16":1,"22":1,"32":2,"35":1,"40":4,"42":5,"44":1,"47":3,"50":3,"57":1,"59":1,"66":2,"69":1}}],["without",{"2":{"10":1,"18":1,"20":1,"66":1}}],["with",{"0":{"7":1,"25":1},"2":{"10":2,"12":1,"13":1,"14":3,"17":1,"19":1,"21":2,"22":3,"23":1,"24":1,"27":3,"32":2,"35":2,"38":2,"40":8,"41":1,"42":4,"44":1,"45":2,"47":1,"48":1,"50":2,"53":1,"54":2,"56":1,"57":2,"59":1,"63":2,"66":1,"73":1,"76":2}}],["widgets",{"0":{"61":1}}],["widget",{"2":{"3":1,"65":1}}],["h1",{"2":{"72":4}}],["huzzah",{"2":{"47":1}}],["html",{"2":{"40":2,"42":2,"50":1}}],["https",{"2":{"35":2,"36":2,"40":6,"42":2,"57":1}}],["http",{"2":{"2":1,"22":1,"36":1,"45":3}}],["hotdog",{"2":{"66":4,"76":9}}],["hot",{"2":{"65":1}}],["hot🥵|js",{"2":{"18":4,"21":6}}],["hooks",{"2":{"27":1}}],["hook",{"2":{"27":1}}],["hooray",{"2":{"18":1}}],["hover",{"2":{"25":1,"37":1,"56":1,"63":1,"73":1}}],["hovering",{"2":{"17":1}}],["how",{"2":{"11":1,"18":1,"29":1,"31":1,"34":1,"38":1,"50":1,"53":2,"60":1,"62":1,"73":1}}],["however",{"2":{"7":1,"14":1,"39":1,"59":1,"67":1}}],["high",{"2":{"64":2}}],["highlighted",{"2":{"37":1}}],["hints",{"2":{"63":1}}],["hint",{"2":{"12":1,"19":2,"62":1}}],["hidden",{"2":{"12":1}}],["hypothesis",{"2":{"12":1}}],["her",{"2":{"76":1}}],["here",{"2":{"5":1,"16":3,"32":2,"40":5,"41":1,"42":2,"44":2,"50":2,"57":1,"59":1,"61":1,"67":1,"70":1}}],["hello",{"2":{"36":1}}],["helps",{"2":{"75":1}}],["helpful",{"2":{"63":1}}],["helpfully",{"2":{"20":1}}],["helper",{"2":{"4":1,"17":1,"21":1,"66":1,"74":2,"76":1}}],["happy",{"2":{"71":1}}],["happens",{"2":{"12":1,"15":1,"30":3,"48":1,"56":1}}],["happened",{"2":{"11":1,"76":1}}],["hard",{"2":{"55":1,"77":1}}],["had",{"2":{"17":1}}],["having",{"2":{"16":1}}],["haven",{"2":{"9":1}}],["have",{"2":{"3":1,"11":2,"13":3,"14":2,"34":1,"38":3,"39":3,"47":2,"48":1,"55":1,"58":1,"64":1,"71":1,"73":2,"75":1,"76":4}}],["handling",{"2":{"54":2}}],["handled",{"2":{"16":1}}],["handle",{"2":{"16":1,"19":1,"20":1,"32":1}}],["handler",{"2":{"3":1,"14":1}}],["handy",{"2":{"5":1}}],["has",{"2":{"3":1,"10":1,"16":2,"24":1,"31":1,"38":1,"42":1,"56":4,"58":2,"63":1,"65":1,"69":2,"70":2,"71":2,"73":2,"75":1}}],["d",{"2":{"41":1,"50":1,"71":1}}],["data",{"2":{"28":1,"39":1}}],["dune",{"0":{"38":1,"39":1,"40":1},"1":{"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1},"2":{"18":1,"38":2,"39":14,"40":23,"41":2,"42":11,"46":1,"47":4,"48":1,"49":6,"50":3,"65":3}}],["deeper",{"2":{"53":1}}],["deleting",{"2":{"50":1}}],["delete",{"2":{"46":2,"48":1}}],["delimited",{"2":{"14":1}}],["detour",{"2":{"43":1}}],["detail",{"2":{"22":1,"73":1}}],["details",{"2":{"14":2,"24":1,"32":1,"41":1,"50":1}}],["describe",{"2":{"49":1}}],["describes",{"2":{"49":1}}],["designed",{"2":{"38":1}}],["despite",{"2":{"32":1}}],["default`",{"2":{"40":2,"42":2}}],["defaultformatter",{"2":{"37":2}}],["default",{"2":{"36":1,"40":2,"41":4,"42":2,"45":5}}],["defined",{"2":{"23":1,"50":1,"61":1}}],["define",{"2":{"14":2,"21":1,"27":1,"68":1,"69":1}}],["depends",{"2":{"45":1}}],["dependencies",{"2":{"36":1,"40":4,"42":4,"47":1}}],["depending",{"2":{"35":1,"38":1}}],["decides",{"2":{"66":1,"67":1}}],["decide",{"2":{"65":1}}],["decimals",{"2":{"10":3}}],["decrement",{"2":{"62":1}}],["decremented",{"2":{"54":1}}],["declaring",{"2":{"44":1}}],["declare",{"2":{"32":1}}],["decorate",{"2":{"22":1,"24":1}}],["developed",{"2":{"47":1}}],["developers",{"0":{"0":1,"51":1},"1":{"1":1,"2":1,"52":1,"53":1,"54":1},"2":{"14":1,"21":1,"32":1,"50":1,"64":1,"76":1}}],["development",{"2":{"41":2,"45":2}}],["developing",{"2":{"22":1}}],["dev",{"2":{"22":1,"42":1,"45":1,"73":1}}],["devs",{"2":{"22":1,"36":5,"37":1,"39":2}}],["degrees",{"2":{"19":1,"21":1}}],["deal",{"2":{"14":1}}],["doing",{"2":{"47":1}}],["docendo",{"2":{"77":1}}],["documentation",{"2":{"47":1}}],["docs",{"2":{"14":1,"40":2,"60":1}}],["done",{"2":{"56":1,"76":1}}],["don",{"2":{"32":2,"38":1,"40":2,"74":1}}],["dom",{"2":{"26":4,"42":1}}],["downloading",{"2":{"36":1}}],["download",{"0":{"36":1}}],["down",{"2":{"17":1,"26":1}}],["does",{"2":{"16":1,"25":1,"26":1,"74":1}}],["doesn",{"2":{"11":1,"15":1,"26":1,"29":1,"31":1,"39":1,"64":1,"71":1}}],["do",{"2":{"6":1,"8":1,"12":2,"18":1,"35":2,"38":1,"48":1,"53":1,"62":1,"67":1,"76":1}}],["disco",{"2":{"77":1}}],["discover",{"2":{"59":1}}],["discuss",{"2":{"73":1}}],["distinction",{"2":{"55":1}}],["displays",{"2":{"25":1}}],["display",{"2":{"5":1,"28":1,"45":1,"63":3}}],["digestible",{"2":{"52":1}}],["digits",{"2":{"10":1}}],["dirs",{"2":{"40":3}}],["directories",{"2":{"40":4,"49":2}}],["directory",{"0":{"42":1,"45":1},"2":{"22":1,"39":1,"40":1,"41":1,"42":4,"44":3,"45":3,"46":2,"47":4,"65":2}}],["differences",{"2":{"22":2}}],["difference",{"2":{"16":1,"23":1}}],["differently",{"2":{"55":1}}],["different",{"2":{"14":1,"17":1,"63":1,"74":1,"76":1}}],["didn",{"2":{"27":1,"55":1,"76":1}}],["did",{"2":{"16":1,"48":1}}],["divfile",{"2":{"50":1}}],["div",{"2":{"3":4,"4":4,"5":4,"6":4,"7":8,"8":4,"9":4,"10":4,"11":4,"15":4,"22":4,"27":4,"29":4,"50":5,"61":8,"64":4,"72":4,"76":1}}],["my",{"2":{"22":2}}],["mismatch",{"2":{"71":1}}],["missing",{"2":{"50":2}}],["mistake",{"2":{"32":1,"50":1}}],["minimal",{"2":{"39":1}}],["minimum",{"2":{"18":1}}],["might",{"2":{"8":1,"11":1,"12":1,"14":1,"15":1,"17":1,"36":1,"39":1,"43":1,"48":1,"55":1,"71":2}}],["multiple",{"2":{"61":1,"73":1}}],["multiples",{"2":{"23":1}}],["much",{"2":{"16":1,"38":1,"41":1,"53":1,"54":1}}],["must",{"2":{"4":1,"9":1,"13":1,"14":1,"22":3,"25":1,"41":1,"71":1,"76":2}}],["mouth",{"2":{"76":1}}],["moment",{"2":{"56":1}}],["motivation",{"0":{"52":1}}],["monorepo",{"0":{"47":1},"2":{"47":2}}],["move",{"2":{"42":1,"74":1,"76":2}}],["modify",{"2":{"27":1,"35":2}}],["modes",{"2":{"40":2,"42":2}}],["mode",{"2":{"22":1,"41":2,"45":2}}],["modules",{"0":{"23":1},"2":{"23":4,"27":1,"31":1,"40":6,"42":2,"66":1}}],["module",{"2":{"17":1,"22":2,"23":2,"27":3,"40":4,"41":1,"42":5,"54":1,"56":2,"61":4,"62":1,"66":2,"72":1,"74":2,"75":2,"76":7}}],["most",{"2":{"12":1,"47":1,"50":1}}],["more",{"2":{"4":1,"8":1,"9":1,"10":1,"14":2,"18":1,"20":1,"22":1,"24":1,"26":1,"29":1,"32":1,"39":2,"40":1,"41":1,"50":1,"54":1,"61":1,"62":1,"73":1,"75":1}}],["madame",{"2":{"65":1,"66":1,"67":1,"76":1}}],["made",{"2":{"15":1}}],["main",{"2":{"41":1,"75":1}}],["maintain",{"2":{"24":1}}],["master",{"2":{"35":2}}],["manager",{"2":{"35":1}}],["manually",{"2":{"27":1,"39":1}}],["many",{"2":{"17":1,"34":1,"35":1,"38":1,"39":1,"52":1,"63":1}}],["making",{"2":{"18":1}}],["makefiles",{"2":{"49":1}}],["makefilesrc",{"2":{"42":1}}],["makefile",{"0":{"43":1,"44":1,"45":1},"2":{"42":2,"43":2,"44":5,"45":2,"47":1,"48":1,"50":6,"65":3}}],["makeprops",{"2":{"32":2}}],["makepropsfile",{"2":{"32":1}}],["makes",{"2":{"32":1,"38":1,"39":1,"55":1,"66":1,"75":1}}],["make",{"0":{"24":1,"69":1},"2":{"3":2,"4":2,"13":1,"15":2,"17":1,"20":1,"22":7,"24":3,"26":1,"27":4,"29":3,"32":3,"36":9,"39":1,"42":6,"43":1,"44":6,"45":2,"49":2,"52":1,"53":1,"58":1,"61":16,"62":2,"64":4,"69":4,"70":3,"71":4,"72":3,"75":1,"76":5}}],["maybe",{"2":{"76":1}}],["may",{"2":{"17":2,"38":1,"59":1,"76":1}}],["mapi",{"0":{"73":1},"2":{"73":4,"75":1,"76":2}}],["map",{"0":{"17":1},"2":{"17":13,"18":4,"20":1,"21":6,"54":1,"70":4,"71":10,"73":2,"75":3}}],["matched",{"2":{"16":2,"32":2}}],["matching",{"2":{"16":3,"32":2,"67":2,"75":1}}],["match",{"2":{"7":1,"16":2,"32":2,"67":1,"71":1}}],["menu",{"2":{"66":1,"74":1,"76":1}}],["mesages",{"2":{"56":1}}],["messages",{"2":{"39":2,"63":1}}],["message",{"2":{"18":1,"26":1}}],["mel",{"2":{"40":2}}],["melange",{"0":{"0":1,"41":1,"51":1,"56":1},"1":{"1":1,"2":1,"52":1,"53":1,"54":1},"2":{"3":1,"12":1,"14":2,"18":1,"21":1,"22":2,"32":1,"36":7,"37":1,"38":1,"39":11,"40":18,"41":5,"42":13,"43":1,"46":1,"47":4,"48":1,"49":3,"50":1,"52":2,"54":2,"56":5,"57":2,"58":1,"60":1,"61":2,"62":1,"63":1,"64":1,"65":1,"70":2,"76":1}}],["metadata",{"2":{"39":3,"49":1}}],["method",{"2":{"35":1,"70":2,"73":1,"75":2}}],["methods",{"2":{"3":1}}],["mean",{"2":{"50":1}}],["means",{"2":{"16":1,"44":1,"45":1,"69":1,"70":1}}],["meaning",{"2":{"7":1,"16":1,"24":1,"26":1,"44":1}}],["measure",{"2":{"6":1}}],["leave",{"2":{"71":1}}],["learning",{"2":{"53":1}}],["learn",{"2":{"52":1}}],["leverage",{"2":{"53":1}}],["level",{"2":{"39":1}}],["less",{"2":{"16":1,"19":1,"21":1,"75":1}}],["left",{"2":{"16":1,"28":1,"56":2}}],["lets",{"2":{"40":2,"42":2}}],["let",{"2":{"3":7,"4":9,"5":1,"12":1,"15":9,"17":1,"21":3,"22":3,"24":1,"26":1,"27":8,"29":1,"32":2,"35":1,"36":1,"42":4,"43":1,"55":6,"56":6,"58":3,"60":3,"61":13,"62":1,"64":5,"66":1,"67":3,"68":2,"69":2,"70":4,"71":4,"72":6,"76":11}}],["large",{"2":{"62":1}}],["layout",{"2":{"41":1}}],["lang",{"2":{"39":2}}],["language=reason",{"2":{"57":1}}],["language",{"2":{"32":1,"39":2,"53":2}}],["label",{"2":{"44":1}}],["labeled",{"0":{"10":1},"2":{"10":4,"13":1,"54":1,"69":1,"70":1,"75":1}}],["labs",{"2":{"37":1}}],["later",{"2":{"18":1,"24":1,"39":1,"46":1,"73":1,"76":1,"77":1}}],["latest",{"2":{"14":1}}],["last",{"0":{"5":1,"28":1},"2":{"5":1,"12":1,"15":1,"28":1,"31":1,"36":1,"54":2,"58":3}}],["ll",{"2":{"9":1,"10":2,"11":1,"15":1,"18":2,"19":1,"22":1,"24":2,"25":1,"26":1,"29":2,"38":1,"39":1,"53":1,"54":1,"56":1,"58":1,"69":1,"71":1,"73":3,"76":3}}],["lowercase",{"2":{"76":1}}],["lowers",{"2":{"67":1}}],["lowest",{"2":{"19":1}}],["low",{"2":{"64":2}}],["locally",{"2":{"47":1}}],["local",{"2":{"45":2}}],["localhost",{"2":{"2":1,"22":1,"36":1,"45":1}}],["long",{"2":{"17":1}}],["longer",{"2":{"14":3,"47":1}}],["log",{"2":{"12":6,"26":1,"55":8,"56":13,"58":14,"59":10,"60":4,"61":2,"62":2,"64":2,"71":9}}],["logic",{"2":{"5":1,"11":1,"21":1}}],["looks",{"2":{"40":1,"73":1}}],["look",{"2":{"12":1,"15":1,"17":1,"18":1,"27":1,"40":2,"42":3,"50":1,"61":1,"62":1,"64":1,"71":1,"74":1,"76":2}}],["lot",{"2":{"10":2,"70":1}}],["live",{"2":{"61":1}}],["live=off",{"2":{"57":1}}],["lives",{"2":{"44":1}}],["libraries",{"2":{"40":7,"41":1,"42":6}}],["library",{"2":{"17":1,"62":1}}],["lisp",{"2":{"39":1}}],["lists",{"2":{"40":2,"42":2}}],["list",{"2":{"4":1,"40":2,"42":2,"50":1,"73":2}}],["link",{"2":{"57":1,"61":1}}],["linux",{"2":{"34":1}}],["lines",{"2":{"16":2,"71":2}}],["line",{"2":{"4":1,"5":1,"32":2,"39":1,"44":2,"50":3,"56":1,"58":3}}],["little",{"2":{"26":1,"38":1,"61":1,"75":1,"76":1}}],["literals",{"2":{"14":1,"55":1,"59":1}}],["limit",{"2":{"10":1}}],["like",{"2":{"4":1,"8":1,"15":1,"17":1,"18":1,"23":1,"35":1,"40":1,"42":1,"44":1,"50":1,"56":1,"59":1,"64":1,"71":1,"76":4}}],["lt",{"2":{"3":6,"4":6,"5":6,"6":6,"7":12,"8":6,"9":6,"10":6,"11":6,"12":2,"14":2,"15":6,"21":4,"22":4,"26":2,"27":14,"29":16,"32":2,"35":2,"42":4,"50":2,"58":4,"61":34,"64":16,"69":12,"70":22,"71":26,"72":12,"73":2,"76":38}}],["++",{"0":{"6":1},"2":{"6":3,"7":4,"8":2,"9":2,"10":2,"11":2,"13":1,"15":2,"16":4,"17":2,"18":4,"21":6,"73":2,"76":2}}],["+",{"2":{"3":3,"4":2,"12":2,"15":2,"27":4,"29":4,"53":2,"59":4,"61":8,"62":1,"64":4,"70":2,"71":2,"76":2}}],["5em",{"2":{"61":4}}],["58",{"2":{"59":1,"64":2}}],["58js",{"2":{"59":1}}],["55",{"2":{"58":2}}],["5",{"2":{"3":2,"4":2,"12":2,"15":2,"50":4,"58":2,"62":2,"64":4,"73":1,"76":2}}],["5173",{"2":{"2":1}}],["000l",{"2":{"62":2}}],["000",{"2":{"62":4}}],["00",{"2":{"19":1,"21":1}}],["0",{"2":{"3":6,"4":6,"15":6,"18":4,"19":1,"21":6,"27":2,"39":6,"40":4,"57":1,"58":2,"59":19,"60":2,"61":6,"62":1,"64":8,"70":2,"71":2,"76":2}}],["9",{"2":{"3":2,"4":2,"15":2}}],["==",{"2":{"8":2,"9":2,"10":2,"11":2,"15":2,"19":1,"21":2,"58":6}}],["=",{"2":{"3":21,"4":24,"5":2,"6":2,"7":12,"8":6,"9":6,"10":6,"11":6,"12":8,"14":5,"15":28,"16":9,"17":17,"18":10,"21":28,"22":6,"24":1,"25":1,"26":6,"27":22,"29":8,"32":4,"42":12,"55":8,"56":12,"58":8,"60":4,"61":40,"62":2,"64":18,"66":10,"67":20,"68":12,"69":4,"70":12,"71":16,"72":14,"73":6,"76":40}}],["fssl",{"2":{"35":2}}],["flex",{"2":{"29":2,"61":4,"64":2}}],["floats",{"2":{"59":1,"63":1}}],["floatfromstring",{"2":{"21":5}}],["floatcelsius",{"2":{"11":1}}],["float",{"0":{"16":1},"2":{"5":7,"6":4,"7":9,"8":4,"9":4,"10":6,"11":13,"15":4,"16":9,"17":14,"18":9,"19":5,"21":17,"54":1,"55":5,"56":5,"58":10,"59":2,"60":2,"62":1,"63":2,"64":3,"69":2,"70":2,"71":2,"74":1,"76":2}}],["fun",{"0":{"68":1},"2":{"68":7,"75":1,"76":4}}],["func",{"2":{"17":4}}],["functionality",{"2":{"16":1}}],["function",{"0":{"24":1},"2":{"4":3,"10":1,"11":2,"12":2,"13":2,"14":4,"16":2,"17":4,"19":1,"21":1,"22":2,"24":1,"25":2,"28":1,"31":1,"32":1,"50":1,"54":1,"61":3,"66":1,"69":2,"70":1,"73":2,"74":1,"75":4,"76":4}}],["functions",{"0":{"4":1},"2":{"4":4,"11":1,"12":1,"13":1,"15":2,"17":2,"20":2,"31":1,"66":1,"68":1,"73":1,"74":1,"75":2}}],["fully",{"2":{"61":1}}],["full",{"2":{"39":1,"50":1}}],["future",{"2":{"29":1,"47":1}}],["further",{"2":{"26":1}}],["f",{"2":{"18":1}}],["few",{"2":{"52":1}}],["feeling",{"2":{"65":1}}],["feel",{"2":{"46":1}}],["feeding",{"2":{"11":1}}],["fetch",{"2":{"36":1}}],["features",{"2":{"38":1,"53":1,"63":1}}],["feature",{"2":{"11":1,"38":1,"56":1}}],["friends",{"2":{"57":1}}],["friendly",{"2":{"8":1}}],["front",{"2":{"48":1,"50":1}}],["frontend",{"2":{"22":1,"53":1}}],["fromstring",{"2":{"19":1,"21":3}}],["from",{"2":{"11":2,"12":1,"14":3,"16":1,"17":1,"21":1,"23":1,"28":1,"32":1,"37":1,"40":6,"42":3,"45":1,"46":1,"48":1,"50":1,"53":1,"54":2,"55":1,"58":1,"59":1,"61":1,"65":1,"66":1,"76":2}}],["foo",{"2":{"55":8,"56":13,"58":9,"60":5}}],["focus",{"2":{"54":1}}],["four",{"2":{"48":1,"50":1}}],["found",{"2":{"14":1,"21":1,"32":1,"39":1,"50":2,"64":1,"76":1}}],["folder",{"2":{"40":4,"42":2}}],["following",{"2":{"10":1,"12":1,"27":1,"38":1,"70":1,"71":1}}],["forgot",{"2":{"73":1}}],["forget",{"2":{"15":1,"16":1}}],["forces",{"2":{"75":1}}],["force",{"2":{"66":1,"67":1}}],["fortunately",{"2":{"50":1}}],["forth",{"2":{"18":1}}],["forward",{"2":{"47":2}}],["format",{"2":{"74":1,"76":8}}],["formatonsave",{"2":{"37":2}}],["formatting",{"2":{"37":1}}],["form",{"2":{"3":5,"4":3,"15":2}}],["for",{"0":{"0":1,"47":1,"51":1,"68":1},"1":{"1":1,"2":1,"52":1,"53":1,"54":1},"2":{"3":2,"4":1,"9":1,"13":1,"14":4,"16":1,"17":2,"21":2,"22":1,"23":1,"24":1,"27":1,"28":1,"32":4,"34":1,"36":5,"37":2,"38":3,"39":7,"40":5,"41":6,"42":4,"44":1,"45":2,"46":1,"47":3,"48":2,"49":3,"50":4,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"61":2,"64":2,"65":1,"66":3,"68":1,"70":1,"71":1,"76":3}}],["famed",{"2":{"65":1}}],["familiar",{"2":{"9":1,"27":1,"44":1}}],["fairly",{"2":{"17":1,"27":1}}],["failed",{"2":{"26":2,"42":2,"61":2,"72":2}}],["fails",{"2":{"16":2}}],["fail",{"2":{"15":1,"66":1}}],["failure",{"2":{"7":2,"16":1}}],["fallback",{"2":{"9":1}}],["fahrenheit",{"2":{"3":1,"5":2,"6":1,"7":8,"8":4,"9":4,"10":5,"11":4,"15":4,"16":7,"17":4,"18":15,"19":1,"21":34,"54":1}}],["fix",{"2":{"58":1,"73":1}}],["fixed",{"2":{"45":1}}],["find",{"2":{"26":4,"42":2,"61":2,"72":2}}],["finally",{"2":{"5":1,"18":1}}],["first",{"2":{"17":1,"18":1,"29":1,"40":1,"54":1,"55":1,"66":1}}],["field",{"2":{"4":1,"40":4,"41":1,"42":4,"50":1}}],["fields",{"2":{"3":3,"13":2,"39":2,"41":1}}],["files",{"0":{"40":1},"2":{"27":1,"39":1,"40":5,"41":3,"42":5,"47":1,"49":1,"50":2,"61":1,"65":1}}],["file",{"0":{"39":1},"2":{"3":1,"16":1,"23":1,"27":2,"32":1,"37":1,"39":3,"40":4,"41":1,"42":1,"44":1,"46":3,"47":3,"49":1,"50":1,"65":1,"70":1,"71":1,"76":1}}],["impressive",{"2":{"61":1}}],["implicit",{"2":{"58":1}}],["implementation",{"2":{"17":1}}],["io",{"2":{"40":4,"42":2}}],["i",{"2":{"26":1}}],["identifier",{"2":{"14":1}}],["idea",{"2":{"4":1,"67":1}}],["if",{"0":{"9":1},"2":{"3":1,"4":1,"7":3,"8":1,"9":6,"10":1,"13":3,"15":1,"16":5,"17":2,"18":1,"19":2,"22":1,"25":1,"26":4,"27":1,"30":2,"32":2,"36":1,"39":1,"41":2,"47":1,"48":1,"54":1,"66":2,"67":1,"71":2,"73":1}}],["isnan",{"2":{"19":1,"21":2}}],["isn",{"2":{"11":1,"29":1,"44":1,"50":1,"63":1}}],["is",{"2":{"3":1,"4":2,"5":1,"7":2,"8":1,"9":1,"10":2,"13":1,"14":1,"15":1,"16":9,"17":6,"18":1,"19":1,"20":2,"21":1,"22":1,"23":1,"24":1,"25":1,"26":2,"27":1,"28":1,"29":1,"31":1,"32":11,"35":1,"36":1,"38":2,"39":5,"40":13,"41":3,"42":6,"43":1,"44":6,"45":1,"47":1,"48":1,"49":2,"50":2,"51":1,"52":1,"53":1,"55":2,"56":2,"57":1,"58":1,"59":1,"62":1,"63":2,"64":2,"66":3,"67":1,"68":2,"70":4,"71":1,"73":2,"74":1,"75":5,"76":1}}],["itemrows",{"2":{"71":4}}],["items",{"2":{"66":1,"69":1,"70":6,"71":8,"72":4,"74":1,"76":4}}],["item",{"0":{"66":1,"69":1},"2":{"65":2,"66":6,"67":3,"68":1,"69":8,"70":12,"71":20,"73":8,"74":3,"76":29}}],["its",{"2":{"3":1,"17":1,"38":1,"44":1,"47":2,"50":1,"52":1,"53":1,"54":1,"56":1,"65":1}}],["it",{"2":{"3":4,"4":1,"6":1,"7":2,"8":3,"9":3,"10":4,"12":6,"14":1,"15":1,"16":4,"17":3,"18":1,"19":1,"22":2,"24":1,"25":2,"26":4,"27":2,"28":1,"29":1,"32":1,"35":3,"36":1,"38":2,"39":4,"40":6,"41":1,"42":2,"44":1,"45":3,"46":1,"47":1,"50":2,"56":2,"57":1,"58":1,"65":2,"66":1,"67":1,"68":3,"71":2,"73":6,"74":3,"76":1}}],["in64",{"2":{"64":1}}],["infer",{"2":{"55":1}}],["info",{"2":{"41":1,"47":1}}],["increment",{"2":{"62":1}}],["incremented",{"2":{"54":1}}],["includes",{"2":{"43":1}}],["include",{"2":{"40":3,"41":1,"49":1}}],["indicate",{"2":{"44":1}}],["independent",{"2":{"38":1,"39":1}}],["indexes",{"2":{"76":1}}],["index",{"0":{"72":1},"2":{"22":1,"32":3,"41":4,"42":3,"45":4,"46":1,"50":2,"65":2,"72":1,"73":6,"76":4}}],["initial",{"2":{"70":1}}],["initially",{"2":{"14":1}}],["init",{"2":{"35":3,"36":3}}],["invocations",{"2":{"56":1}}],["invoke",{"2":{"31":1}}],["invokes",{"2":{"17":1}}],["invoked",{"2":{"14":2}}],["invalid",{"2":{"8":1,"15":1}}],["int64",{"2":{"62":6,"64":4}}],["intthis",{"2":{"58":1}}],["intline",{"2":{"56":1}}],["introducing",{"2":{"52":1}}],["introduction",{"0":{"38":1},"1":{"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1},"2":{"52":1}}],["introduce",{"2":{"10":1,"53":1}}],["interactive",{"2":{"56":1}}],["interest",{"2":{"38":1,"40":1,"41":1,"49":1}}],["interesting",{"2":{"29":1}}],["interested",{"2":{"17":1,"53":1}}],["integer",{"2":{"3":1,"12":1,"28":1,"55":1,"58":1,"62":1,"63":2,"64":1}}],["int",{"2":{"12":1,"27":2,"28":3,"29":2,"54":1,"55":4,"56":7,"58":8,"60":2,"61":4,"73":4,"76":2}}],["into",{"2":{"4":1,"7":1,"24":1,"40":2,"41":1,"42":2,"45":1,"50":1,"53":1,"56":1,"73":1}}],["instances",{"2":{"60":1}}],["installed",{"2":{"22":1,"36":1}}],["install",{"2":{"1":1,"34":1,"35":3,"37":1}}],["installmake",{"2":{"1":1}}],["installation",{"0":{"1":1,"33":1},"1":{"34":1,"35":1,"36":1,"37":1},"2":{"35":1}}],["instead",{"2":{"4":1,"7":1,"8":1,"16":1,"19":2,"21":1,"29":1,"43":1,"45":1,"50":2,"54":1,"56":1,"62":1,"64":2,"73":1,"74":1,"76":1}}],["inside",{"2":{"3":1,"14":1,"22":1,"23":1,"25":1,"30":1,"40":3,"42":2,"50":1,"72":2,"74":2}}],["inputs",{"2":{"63":1}}],["input",{"2":{"3":3,"4":2,"5":2,"6":2,"7":5,"8":3,"9":2,"10":2,"11":2,"12":2,"14":3,"15":3,"16":1,"19":1,"20":1,"54":1}}],["in",{"0":{"61":1,"67":1},"2":{"3":2,"5":1,"7":1,"8":1,"9":7,"10":6,"11":2,"12":2,"13":2,"14":6,"15":2,"16":2,"17":2,"19":1,"21":3,"22":4,"23":2,"25":1,"26":2,"27":2,"28":1,"29":4,"30":2,"31":1,"32":6,"36":1,"37":2,"38":4,"39":5,"40":10,"41":4,"42":8,"43":1,"44":5,"45":4,"46":2,"47":4,"48":2,"49":1,"50":6,"51":1,"53":3,"54":1,"55":1,"56":3,"57":2,"58":2,"59":1,"61":5,"62":2,"63":2,"64":1,"65":1,"66":3,"67":3,"69":1,"70":1,"71":3,"72":1,"73":4,"74":1,"75":3,"76":4}}],["again",{"2":{"74":1}}],["agree",{"2":{"35":1}}],["amp",{"2":{"57":2}}],["audience",{"0":{"53":1}}],["automation",{"2":{"43":1,"49":1}}],["automatically",{"2":{"27":1}}],["auto",{"2":{"37":1}}],["able",{"2":{"45":1,"55":1}}],["above",{"2":{"18":1,"23":1,"32":1}}],["about",{"2":{"3":1,"4":1,"7":1,"14":1,"22":1,"26":1,"27":1,"32":1,"40":1,"41":2,"50":1,"59":1}}],["appropriate",{"2":{"56":1}}],["app=counter",{"2":{"44":1}}],["appear",{"2":{"39":1}}],["apps",{"2":{"38":1,"47":1,"53":1}}],["app",{"0":{"26":1,"42":1},"2":{"22":5,"23":1,"26":4,"27":3,"29":2,"30":1,"31":1,"32":1,"42":7,"44":1,"45":12,"47":4,"48":1,"50":1,"65":1,"72":5}}],["applies",{"2":{"58":1}}],["applications",{"2":{"53":1}}],["application",{"0":{"11":1},"2":{"11":1,"12":2,"13":1,"14":1,"45":2,"54":1}}],["apply",{"0":{"5":1},"2":{"28":1}}],["avoid",{"2":{"67":1}}],["avoids",{"2":{"15":1}}],["available",{"2":{"14":1}}],["adaptable",{"2":{"75":1}}],["adventurous",{"2":{"65":1}}],["advice",{"2":{"47":1}}],["advantages",{"2":{"66":1}}],["advantage",{"2":{"11":1,"16":1}}],["addition",{"2":{"59":1}}],["additions",{"2":{"17":1}}],["adding",{"2":{"43":1,"75":1}}],["added",{"2":{"42":1,"43":1,"66":1,"76":1}}],["add",{"2":{"15":1,"18":1,"19":1,"21":2,"29":1,"37":1,"50":1,"61":1,"62":2,"64":4,"66":5,"70":1,"71":1,"74":2,"76":3}}],["addfive",{"2":{"12":8,"14":1}}],["acc",{"2":{"70":4,"71":4,"76":4}}],["accordingly",{"2":{"67":1}}],["accepted",{"2":{"40":2}}],["accepts",{"2":{"17":1,"39":1}}],["accept",{"2":{"16":1,"63":1}}],["access",{"2":{"3":1,"13":1,"16":2}}],["actual",{"2":{"71":1}}],["actually",{"2":{"11":1,"17":1,"50":1,"71":1}}],["action",{"2":{"44":1,"72":1}}],["alias",{"2":{"61":2}}],["along",{"2":{"38":1}}],["alternate",{"2":{"31":1,"68":1}}],["already",{"2":{"22":1,"39":1,"53":1,"59":1}}],["also",{"2":{"8":1,"9":1,"13":2,"17":1,"31":1,"34":1,"40":1,"41":1,"46":1,"55":1,"57":1,"59":1,"61":1,"65":1,"66":1,"68":1,"73":1}}],["allows",{"2":{"18":2,"26":1,"40":4,"67":1}}],["allowing",{"2":{"5":1}}],["all",{"2":{"5":1,"15":1,"22":1,"23":1,"27":1,"32":1,"36":1,"39":1,"40":5,"42":2,"58":1,"59":1,"61":1,"67":1,"69":1,"70":1,"76":2}}],["always",{"2":{"4":1,"9":1}}],["arrayitems",{"2":{"73":1}}],["array",{"0":{"71":1,"73":1},"2":{"64":1,"70":15,"71":30,"73":11,"75":10,"76":9}}],["arrow",{"2":{"4":1}}],["arithmetic",{"0":{"59":1},"2":{"59":3,"63":2}}],["artifacts",{"2":{"40":2,"41":1,"42":2}}],["around",{"2":{"17":2,"63":1}}],["aren",{"2":{"9":1,"30":1}}],["are",{"0":{"23":1},"2":{"4":1,"13":1,"14":5,"16":1,"23":2,"27":1,"31":1,"34":3,"35":1,"39":1,"40":1,"41":2,"47":3,"52":1,"56":1,"58":1,"59":1,"60":1,"61":1,"63":3,"66":1,"71":1,"75":2,"76":1,"77":1}}],["arguments",{"2":{"10":1,"11":1,"13":3,"73":1,"75":1}}],["argument",{"0":{"10":1},"2":{"4":2,"10":4,"11":4,"12":1,"13":1,"16":1,"17":2,"24":1,"54":1,"69":1,"70":1}}],["after",{"2":{"4":2,"6":1,"15":1,"35":1,"42":1,"71":1,"75":1,"76":2}}],["assume",{"2":{"47":1}}],["ascii",{"2":{"14":1}}],["as",{"2":{"3":1,"4":1,"9":2,"10":1,"13":1,"14":1,"22":1,"24":1,"27":1,"34":1,"36":1,"39":1,"40":3,"42":2,"57":1,"63":2,"65":1,"66":1,"67":2,"75":1}}],["anatomy",{"0":{"44":1}}],["annotating",{"2":{"56":1}}],["annotations",{"2":{"13":1,"37":1}}],["annotated",{"2":{"4":1}}],["another",{"2":{"4":1,"5":1,"16":1,"19":1,"21":1,"22":1,"41":1,"43":1,"56":1,"58":1,"69":1,"74":1}}],["an",{"2":{"3":1,"8":1,"9":2,"12":1,"14":1,"15":1,"16":3,"17":3,"24":1,"26":2,"28":1,"29":1,"31":2,"32":2,"41":1,"44":1,"47":1,"56":3,"57":1,"58":4,"62":1,"64":1,"68":1,"69":1,"70":2,"71":2,"75":1}}],["anywhere",{"2":{"50":1,"74":1}}],["anymore",{"2":{"46":1}}],["anything",{"2":{"4":1,"7":1,"40":1}}],["any",{"2":{"3":1,"7":2,"13":1,"14":1,"17":2,"30":1,"65":1,"67":2,"76":1}}],["and",{"0":{"36":1,"54":1},"2":{"3":2,"5":1,"9":2,"10":2,"11":1,"12":2,"13":2,"14":3,"16":4,"17":3,"18":4,"21":1,"22":2,"23":1,"24":3,"26":1,"28":1,"29":2,"31":1,"34":1,"36":3,"37":3,"38":1,"39":3,"40":3,"41":1,"42":2,"43":1,"44":1,"45":2,"47":2,"48":1,"49":1,"50":3,"52":4,"53":1,"54":1,"55":2,"56":4,"58":1,"60":1,"61":1,"62":1,"63":3,"65":2,"66":2,"68":1,"70":1,"73":1,"74":2,"75":1,"76":5}}],["a",{"0":{"68":1},"2":{"3":3,"4":3,"5":1,"7":4,"8":1,"9":6,"10":7,"11":5,"12":4,"13":3,"14":5,"15":1,"16":6,"17":20,"18":6,"19":4,"20":2,"21":5,"22":3,"23":2,"26":1,"27":5,"28":3,"29":3,"31":1,"32":7,"34":3,"36":3,"38":2,"39":6,"40":7,"41":1,"42":7,"43":2,"44":6,"45":4,"47":5,"48":2,"49":1,"50":7,"51":1,"52":2,"53":1,"55":1,"56":3,"57":1,"58":3,"60":1,"61":3,"62":1,"63":1,"64":1,"65":2,"66":7,"67":4,"68":2,"69":5,"70":4,"71":5,"73":12,"74":2,"75":10,"76":10}}],["attributes",{"2":{"40":6}}],["attribute",{"2":{"24":1,"30":1,"32":1}}],["at",{"2":{"2":1,"12":1,"17":1,"32":1,"39":1,"40":1,"44":1,"52":1,"56":1,"62":1,"66":1,"71":2,"76":1,"77":1}}],["tbody",{"2":{"70":4,"71":5,"76":4}}],["td",{"2":{"69":8,"70":8,"71":8,"76":20}}],["tutorial",{"2":{"53":1}}],["turns",{"2":{"71":1}}],["turn",{"2":{"41":1}}],["typing",{"2":{"75":1}}],["typical",{"2":{"36":1}}],["typeof",{"2":{"60":4}}],["typescript",{"2":{"76":1}}],["types",{"0":{"55":1},"1":{"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":1},"2":{"3":1,"54":1,"55":4,"56":1,"60":2,"63":1,"66":1,"71":1,"76":1}}],["type",{"0":{"66":1},"2":{"3":2,"4":1,"9":1,"13":4,"16":1,"17":10,"24":2,"25":2,"29":1,"31":1,"32":1,"35":1,"37":1,"56":7,"57":1,"58":6,"60":1,"63":3,"64":1,"66":5,"69":1,"70":3,"71":9,"73":1,"74":1,"75":2,"76":4}}],["title",{"2":{"54":1}}],["time",{"2":{"14":1,"38":1,"39":1,"61":1,"66":1}}],["tip",{"2":{"14":1}}],["teaches",{"2":{"53":1}}],["tests",{"2":{"40":1}}],["technically",{"2":{"39":1}}],["tell",{"2":{"40":3}}],["telling",{"2":{"32":1}}],["tells",{"2":{"4":1,"40":1,"41":1,"44":1}}],["template",{"2":{"22":1,"36":6,"41":1}}],["temperature",{"2":{"3":1,"18":1,"19":2,"21":1}}],["terminal",{"2":{"22":1}}],["terms",{"2":{"16":1}}],["ternary",{"0":{"8":1},"2":{"8":1,"9":2,"13":1,"18":1,"54":1}}],["text",{"2":{"14":1,"21":4}}],["treated",{"2":{"75":1}}],["treating",{"2":{"3":1}}],["tr",{"2":{"69":4,"70":4,"71":4,"76":8}}],["traditional",{"2":{"54":1}}],["translate",{"2":{"63":1}}],["translated",{"2":{"50":1,"60":1}}],["transpiled",{"2":{"49":1}}],["transform",{"2":{"40":2,"42":2,"50":1}}],["track",{"2":{"15":1}}],["true",{"2":{"37":2}}],["trusting",{"2":{"4":1}}],["trigger",{"2":{"32":1}}],["trim",{"2":{"19":1,"21":3}}],["try",{"2":{"12":1,"30":1,"52":1,"56":2,"59":1,"71":1}}],["two",{"2":{"3":1,"11":1,"13":2,"62":1,"64":2,"66":2,"71":1}}],["t",{"0":{"4":1,"66":1},"2":{"3":5,"4":1,"7":1,"9":2,"11":2,"13":3,"14":2,"15":2,"16":1,"26":3,"27":1,"29":3,"30":1,"31":1,"32":2,"38":1,"39":1,"40":2,"42":2,"44":1,"46":1,"50":1,"54":1,"55":1,"59":2,"61":3,"63":1,"64":1,"66":11,"67":13,"69":3,"70":8,"71":1,"72":4,"74":2,"75":1,"76":14}}],["taste",{"2":{"68":1}}],["talk",{"2":{"26":1}}],["table",{"2":{"69":2,"70":4,"71":4,"76":5}}],["tabs",{"2":{"50":1}}],["tab",{"2":{"22":1,"36":1,"37":1,"45":1,"48":2,"50":4}}],["take",{"2":{"11":2,"12":1,"29":1,"31":1,"36":1,"43":1,"62":1,"76":1}}],["takes",{"2":{"3":1,"11":2,"12":1,"13":2,"16":1,"17":1,"21":1,"24":1,"29":1}}],["targets",{"2":{"40":2,"42":2,"44":1}}],["target",{"2":{"3":5,"4":3,"15":2,"40":2,"41":3,"42":2,"44":2,"49":1}}],["totally",{"2":{"76":1}}],["total",{"2":{"70":6,"71":6,"76":6}}],["toemoji",{"2":{"68":3,"69":2,"76":5}}],["together",{"2":{"58":1}}],["too",{"2":{"52":1}}],["tools",{"2":{"52":1}}],["tool",{"2":{"43":1,"49":1}}],["toprice",{"2":{"66":5,"67":8,"68":3,"69":2,"70":2,"71":2,"76":9}}],["topics",{"0":{"54":1},"2":{"54":1}}],["top",{"2":{"39":1,"56":1}}],["tostringwithradix",{"2":{"12":1}}],["tofixedwithprecision",{"2":{"10":4,"11":5,"15":2,"16":2,"17":6,"18":4,"21":6,"69":2,"70":2,"71":2,"74":1,"76":2}}],["to",{"0":{"38":1},"1":{"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1},"2":{"3":4,"4":4,"5":6,"6":1,"7":3,"8":1,"9":1,"10":1,"11":3,"12":6,"13":2,"14":7,"15":1,"16":6,"17":2,"18":7,"19":2,"20":2,"21":4,"22":7,"23":1,"24":3,"25":2,"26":4,"27":3,"28":8,"29":5,"30":2,"31":2,"32":6,"34":2,"35":5,"36":2,"37":2,"38":3,"39":4,"40":15,"41":8,"42":12,"43":1,"44":4,"45":6,"46":1,"47":5,"49":6,"50":5,"52":3,"53":5,"54":3,"55":2,"57":2,"58":8,"59":1,"60":2,"61":13,"62":3,"63":3,"64":3,"65":4,"66":9,"67":7,"68":4,"69":2,"70":3,"71":12,"72":3,"73":5,"74":5,"75":7,"76":15}}],["throughout",{"2":{"53":1}}],["through",{"2":{"22":1}}],["throw",{"2":{"15":1,"20":1}}],["though",{"2":{"17":1}}],["those",{"2":{"3":1,"20":1,"40":4,"42":5}}],["think",{"2":{"12":1,"39":1}}],["things",{"2":{"49":1,"52":1}}],["thing",{"2":{"4":1,"55":1,"74":1}}],["this",{"2":{"4":1,"7":2,"9":1,"10":1,"11":2,"12":1,"13":1,"14":2,"15":1,"16":6,"17":2,"18":2,"19":1,"21":1,"22":2,"25":1,"27":1,"28":1,"29":1,"31":1,"32":5,"36":1,"37":1,"39":1,"40":2,"41":1,"42":4,"43":1,"44":2,"45":2,"46":1,"47":1,"50":2,"51":1,"52":1,"53":1,"54":1,"55":1,"56":4,"58":2,"59":1,"61":1,"64":2,"66":4,"67":1,"69":2,"70":1,"71":4,"73":2,"76":6}}],["than",{"2":{"4":2,"17":1,"19":1,"21":1,"39":1,"55":1}}],["that",{"0":{"4":1},"2":{"3":1,"4":4,"5":1,"6":1,"7":1,"8":1,"10":1,"11":1,"12":3,"13":1,"14":4,"15":1,"16":8,"17":3,"18":2,"19":1,"20":3,"21":1,"23":2,"24":1,"25":1,"26":1,"27":2,"28":2,"29":1,"31":1,"32":3,"35":1,"36":1,"37":1,"38":1,"39":1,"40":5,"41":2,"42":4,"44":2,"45":1,"47":4,"48":1,"49":1,"50":2,"53":1,"54":2,"55":2,"56":4,"58":2,"59":4,"61":1,"64":1,"66":1,"67":2,"69":1,"70":1,"71":2,"73":2,"74":1,"75":1,"76":3}}],["their",{"2":{"47":1,"56":1,"76":1}}],["these",{"2":{"22":1,"38":1,"42":2}}],["them",{"2":{"13":1,"25":1,"36":1,"38":1,"59":1}}],["therefore",{"2":{"39":1,"52":1,"58":1}}],["there",{"2":{"7":2,"16":1,"23":1,"24":1,"28":1,"30":1,"34":1,"35":1,"44":1,"52":1,"58":1,"66":1,"68":1,"70":1,"71":1}}],["then",{"2":{"5":1,"11":1,"21":1,"28":1,"36":1,"39":1,"42":1,"61":1,"76":2}}],["they",{"0":{"60":1},"2":{"4":2,"6":1,"13":1,"32":1,"63":1,"64":1,"67":1,"76":2}}],["the",{"0":{"24":1,"26":1,"27":1,"28":1,"36":1,"61":1},"2":{"2":1,"3":8,"4":8,"5":5,"6":3,"7":4,"8":2,"9":4,"10":6,"11":6,"12":4,"13":7,"14":14,"15":4,"16":14,"17":10,"18":6,"19":4,"20":3,"21":2,"22":12,"23":5,"24":5,"25":3,"26":11,"27":6,"28":3,"29":3,"30":5,"31":2,"32":9,"35":3,"36":3,"37":4,"38":1,"39":17,"40":30,"41":9,"42":24,"43":2,"44":12,"45":13,"46":6,"47":4,"48":4,"49":11,"50":8,"53":5,"54":4,"55":4,"56":14,"57":4,"58":7,"59":2,"60":2,"61":16,"62":8,"63":3,"64":1,"65":10,"66":13,"67":5,"68":3,"69":4,"70":9,"71":14,"72":3,"73":11,"74":5,"75":8,"76":12,"77":1}}],["old",{"2":{"73":1}}],["oops",{"2":{"73":1}}],["own",{"2":{"47":3,"50":1}}],["overkill",{"2":{"47":1}}],["over",{"2":{"17":1,"20":1,"22":1,"25":1,"28":1,"37":1,"56":1,"65":1,"73":1,"76":1}}],["overview",{"0":{"13":1,"20":1,"31":1,"49":1,"63":1,"75":1}}],["outside",{"2":{"76":1}}],["output",{"2":{"40":2,"41":3,"42":2,"45":4,"56":2,"61":1,"63":2,"71":1}}],["outputs",{"2":{"12":1}}],["out",{"2":{"16":1,"30":1,"32":1,"56":1,"59":1}}],["ourselves",{"2":{"4":1}}],["our",{"2":{"3":1,"11":1,"18":1,"24":1,"27":1,"29":1,"30":1,"36":1,"38":1,"40":1,"41":1,"61":1}}],["occur",{"2":{"12":1}}],["ocamllabs",{"2":{"37":2}}],["ocaml",{"2":{"4":1,"9":3,"11":2,"12":1,"13":1,"14":2,"16":1,"18":1,"23":1,"27":1,"28":1,"31":1,"32":3,"34":1,"35":3,"37":6,"38":1,"41":1,"43":1,"49":1,"52":1,"53":2,"54":2,"55":3,"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"63":2,"66":2,"67":2,"71":2,"73":1}}],["opam",{"0":{"35":1},"2":{"35":11,"39":1,"41":1,"47":1,"50":1}}],["operations",{"2":{"28":1}}],["operators",{"0":{"58":1,"59":1},"2":{"12":1,"58":1,"59":3,"63":3}}],["operator",{"0":{"28":1},"2":{"3":1,"5":1,"6":1,"12":1,"13":2,"28":1,"31":1,"54":1}}],["opened",{"2":{"65":1}}],["open",{"2":{"22":2,"36":1,"37":3,"41":2,"45":3,"73":1}}],["optimization",{"2":{"56":1}}],["optional",{"2":{"73":1}}],["option",{"0":{"15":1,"17":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1,"21":1},"2":{"11":1,"16":2,"17":27,"18":4,"20":4,"21":7,"26":2,"31":1,"41":1,"44":1,"45":1,"54":5}}],["opt",{"0":{"16":1},"2":{"16":5,"17":5,"18":4,"19":2,"21":6}}],["otherwise",{"2":{"26":1}}],["other",{"2":{"4":1,"17":1,"34":1,"36":1,"38":1,"39":1,"59":1,"66":1,"68":1}}],["object",{"2":{"3":1,"13":1,"14":2,"24":1,"29":2,"54":1,"71":1}}],["objects",{"2":{"3":2,"4":1,"13":2,"14":1,"31":1,"61":1}}],["orderitem",{"2":{"74":1,"76":5}}],["order",{"0":{"65":1,"70":1},"1":{"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1},"2":{"39":1,"65":5,"66":3,"69":1,"70":10,"71":9,"72":9,"73":1,"74":2,"76":10}}],["orders",{"2":{"29":1}}],["or",{"2":{"3":1,"9":1,"31":1,"32":1,"36":1,"40":5,"42":2,"46":1,"54":1,"66":2,"68":1,"75":2,"76":2}}],["often",{"2":{"75":1}}],["off",{"2":{"16":1,"71":1}}],["of",{"0":{"16":1,"44":1},"2":{"3":2,"4":2,"5":5,"6":5,"7":8,"8":4,"9":5,"10":8,"11":10,"13":6,"14":5,"15":4,"16":9,"17":18,"18":7,"19":4,"20":1,"21":7,"22":3,"23":2,"24":1,"26":1,"27":2,"28":2,"29":3,"30":1,"31":1,"32":3,"34":1,"38":1,"39":9,"40":7,"41":4,"42":6,"43":2,"44":2,"45":1,"46":1,"48":1,"49":4,"50":4,"53":1,"54":2,"56":3,"57":1,"58":7,"59":1,"60":2,"62":3,"64":2,"65":2,"66":5,"67":1,"69":2,"70":4,"71":4,"73":3,"74":1,"75":3,"76":8}}],["only",{"2":{"11":1,"13":1,"16":1,"17":1,"24":1,"41":1,"42":1,"44":1,"45":1,"47":1,"63":1,"66":1,"71":1,"74":1}}],["on",{"2":{"5":1,"9":1,"14":1,"19":1,"35":1,"38":1,"41":1,"45":1,"49":1,"54":1,"56":1,"61":2,"63":2,"65":1,"70":1,"73":1,"75":1}}],["onclick=",{"2":{"27":4,"29":4,"61":8,"64":4}}],["once",{"2":{"3":1,"52":1,"63":1}}],["onchange",{"2":{"3":1,"4":1,"12":1,"14":5}}],["onchange=",{"2":{"3":2,"4":2,"12":2,"14":2,"15":2}}],["ones",{"2":{"40":1,"41":1}}],["one",{"2":{"3":1,"4":1,"5":1,"10":2,"11":2,"13":2,"23":1,"40":1,"44":1,"58":1,"66":1,"68":1,"73":1,"75":1}}],["check",{"2":{"77":1}}],["chosen",{"2":{"76":1}}],["child",{"2":{"73":2}}],["children",{"2":{"71":1,"76":2}}],["character",{"2":{"50":1}}],["characters",{"2":{"16":2,"32":2,"50":3,"71":2}}],["changing",{"2":{"12":1,"14":1,"66":1,"67":1}}],["changed",{"2":{"41":1}}],["changes",{"2":{"15":1}}],["change",{"2":{"5":1,"41":1,"44":1,"45":1,"58":2,"66":1,"67":1,"71":1,"75":2}}],["chapter",{"2":{"11":1,"14":1,"15":1,"21":1,"26":1,"29":1,"32":2,"50":1,"52":1,"54":1,"61":1,"62":1,"64":1,"65":1,"73":1,"76":1}}],["chapters",{"0":{"54":1},"2":{"10":1,"29":1,"46":1,"47":1}}],["chaining",{"2":{"20":1,"28":1,"31":1,"54":1}}],["chained",{"2":{"11":1}}],["chain",{"2":{"11":2,"17":2}}],["customary",{"2":{"66":1}}],["currency",{"2":{"74":1,"76":10}}],["currently",{"2":{"45":1}}],["current",{"2":{"40":2}}],["curl",{"2":{"35":2}}],["center",{"2":{"61":4}}],["celsiusconverter",{"2":{"3":1,"15":1,"16":2}}],["celsius",{"0":{"3":1,"15":1},"1":{"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1},"2":{"3":7,"4":6,"5":4,"6":2,"7":4,"8":4,"9":4,"10":4,"11":4,"15":10,"16":4,"17":4,"18":6,"21":8,"26":1,"48":1,"50":2,"54":3}}],["cd",{"2":{"36":2}}],["c",{"2":{"35":2,"42":2,"44":3,"71":2}}],["css",{"2":{"29":1,"73":1}}],["click",{"2":{"61":1}}],["cleanup",{"0":{"46":1}}],["clear",{"2":{"6":1,"55":1}}],["clj",{"2":{"39":2,"40":1,"42":1}}],["clone",{"2":{"36":2}}],["class",{"2":{"54":1}}],["classes",{"2":{"29":1}}],["classic",{"2":{"22":1}}],["creating",{"2":{"27":1,"50":1,"65":1}}],["createelement",{"2":{"50":1}}],["created",{"2":{"29":2,"45":1,"47":1,"62":1}}],["creates",{"2":{"14":1,"71":1}}],["create",{"2":{"3":1,"11":1,"18":1,"27":1,"29":1,"31":1,"42":1,"45":1,"47":1,"48":1,"50":1,"70":1,"73":1,"76":2}}],["critical",{"2":{"16":1}}],["crash",{"2":{"7":1,"15":1}}],["cafe",{"2":{"65":1,"66":1,"76":1}}],["caveat",{"2":{"40":2,"42":2}}],["came",{"2":{"32":1}}],["case",{"2":{"10":1,"16":5,"19":1,"20":1,"32":3,"40":2,"42":2,"44":1,"67":1}}],["cases",{"2":{"9":2}}],["catching",{"2":{"7":1,"11":1}}],["catch",{"0":{"7":1},"2":{"7":1,"13":1,"76":1}}],["call",{"2":{"21":1,"71":5,"75":1}}],["calls",{"2":{"17":1,"22":1,"25":1,"28":1,"31":1,"50":2,"71":1}}],["calling",{"2":{"14":1,"29":1}}],["callback",{"2":{"4":1,"12":1,"14":2,"30":1,"73":1}}],["called",{"2":{"3":1,"13":1,"61":1,"65":1,"66":1,"68":1,"76":2}}],["cannedfood",{"2":{"76":1}}],["cannot",{"2":{"58":1}}],["can",{"2":{"3":2,"4":1,"6":1,"7":2,"8":1,"9":3,"10":1,"11":2,"13":5,"14":3,"15":1,"16":2,"17":2,"18":1,"20":2,"21":3,"22":3,"23":1,"28":1,"31":1,"32":1,"34":1,"39":2,"45":1,"46":1,"49":1,"50":2,"54":1,"56":3,"58":1,"59":1,"61":2,"64":2,"65":3,"66":1,"67":1,"68":2,"71":1,"73":2,"76":3}}],["cogito",{"2":{"77":1}}],["collections",{"2":{"71":1}}],["cold",{"2":{"21":1}}],["cold🥶|js",{"2":{"21":4}}],["cold🥶",{"2":{"19":1}}],["corner",{"2":{"56":1}}],["correct",{"2":{"53":1}}],["correctly",{"2":{"4":1,"8":1,"14":1,"19":1}}],["copied",{"2":{"45":1,"65":2}}],["covers",{"2":{"60":1}}],["cover",{"2":{"39":1,"54":2}}],["covered",{"2":{"31":1,"54":1}}],["coffee",{"2":{"36":1}}],["course",{"2":{"76":1}}],["counter",{"0":{"22":1,"27":1,"42":1},"1":{"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1},"2":{"22":1,"27":10,"28":4,"29":3,"30":1,"32":7,"42":11,"44":2,"45":5,"48":2,"50":6,"54":1,"61":14,"62":1,"64":5}}],["couple",{"2":{"17":1}}],["couldn",{"2":{"26":2,"42":2,"61":2,"72":2}}],["could",{"2":{"3":1,"7":1,"9":1,"18":1,"67":1}}],["code=bgv0igzvbya9idqyowpszxqgymfyid0gndiumtsksnmubg9nkgzvbyk7ckpzlmxvzyhiyxipow",{"2":{"57":1}}],["code",{"0":{"37":1,"57":1},"2":{"7":1,"9":1,"14":1,"18":1,"21":1,"24":1,"32":1,"34":2,"37":3,"40":2,"42":2,"49":1,"50":2,"56":2,"57":3,"61":1,"63":2,"64":1,"66":2,"70":1,"71":1,"75":2,"76":1}}],["concepts",{"2":{"52":1}}],["concerned",{"2":{"41":1}}],["concatenate",{"2":{"13":1}}],["concatenation",{"0":{"6":1},"2":{"6":1}}],["convention",{"2":{"66":1,"75":1}}],["convenient",{"2":{"39":1}}],["conversions",{"2":{"58":1}}],["convertcelsius",{"2":{"11":1}}],["converted",{"2":{"7":1,"10":1,"16":1,"18":1}}],["converter",{"0":{"3":1,"15":1},"1":{"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1},"2":{"18":1,"26":1,"48":1,"50":2,"54":2}}],["convert",{"2":{"3":2,"4":2,"5":6,"6":2,"7":4,"8":2,"9":2,"10":2,"11":5,"15":4,"16":2,"17":6,"18":5,"21":6,"25":1,"58":2,"62":1,"75":1}}],["converts",{"2":{"3":1,"12":1,"14":1,"28":2,"54":1}}],["config",{"2":{"50":1}}],["confirmation",{"0":{"65":1},"1":{"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1},"2":{"65":5,"70":1,"71":2,"72":4,"73":1,"76":2}}],["confirm",{"2":{"12":1}}],["confuse",{"2":{"32":1}}],["congratulations",{"2":{"29":1}}],["content",{"0":{"77":1},"2":{"77":1}}],["contents",{"2":{"27":1}}],["containing",{"2":{"69":1}}],["contains",{"2":{"12":2,"14":1,"42":1,"47":1,"61":1,"75":1}}],["contain",{"2":{"3":1,"4":1,"42":1,"49":2,"66":1,"71":1}}],["constants",{"2":{"56":1}}],["constructors",{"2":{"66":2,"67":2,"75":2}}],["constructor",{"2":{"26":1,"66":1,"67":1,"74":1,"76":1}}],["construct",{"2":{"9":1,"18":1}}],["consider",{"2":{"36":1}}],["consisting",{"2":{"17":1}}],["consists",{"2":{"3":1,"40":1}}],["console",{"2":{"26":2,"42":2,"56":6,"63":1,"71":3,"72":2,"73":1}}],["conditionals",{"2":{"18":1,"20":1}}],["conditions",{"2":{"18":1}}],["condition",{"2":{"9":2}}],["combine",{"2":{"67":1}}],["come",{"2":{"54":1}}],["comes",{"2":{"23":1}}],["com",{"2":{"35":2,"36":2}}],["coming",{"2":{"14":1}}],["commissioned",{"2":{"65":1}}],["communicate",{"2":{"40":2}}],["command",{"2":{"36":1,"41":1,"44":2,"45":1,"49":1}}],["commands",{"0":{"2":1},"2":{"49":1}}],["commenting",{"2":{"32":1}}],["comment",{"2":{"16":1,"30":1}}],["commonly",{"2":{"49":1}}],["commonjs",{"2":{"40":2,"42":2}}],["common",{"2":{"9":1,"32":1,"38":1,"43":1,"50":1,"73":1}}],["compare",{"2":{"58":1}}],["comparison",{"0":{"58":1},"2":{"18":1,"58":1,"63":1}}],["complement",{"2":{"53":1}}],["completes",{"2":{"35":1}}],["complete",{"2":{"18":1,"60":1}}],["completely",{"2":{"15":1,"68":1}}],["complex",{"2":{"9":1,"29":1}}],["complaint",{"2":{"18":1}}],["complain",{"2":{"3":1}}],["compiling",{"2":{"63":1}}],["compile",{"2":{"58":1,"59":3,"66":1,"74":1}}],["compiled",{"2":{"40":2,"42":2,"63":2,"71":1}}],["compiles",{"2":{"12":1}}],["compiler",{"2":{"3":2,"4":1,"15":1,"16":1,"20":1,"22":1,"32":1,"40":2,"42":2,"48":1,"56":1,"58":1,"71":1}}],["compilation",{"2":{"9":1,"32":3,"50":1}}],["components",{"0":{"23":1},"2":{"22":1,"23":1,"29":1,"31":1,"38":2,"40":2,"61":1,"63":1,"73":1,"76":1}}],["component",{"0":{"26":1,"27":1,"70":1},"2":{"3":2,"4":2,"11":1,"15":2,"18":1,"22":5,"23":1,"24":2,"26":2,"27":7,"29":1,"30":1,"32":4,"42":3,"45":1,"54":1,"61":5,"62":1,"64":3,"69":5,"70":4,"72":3,"73":1,"74":3,"75":1,"76":6}}],["sweet",{"2":{"56":1}}],["switch",{"0":{"7":1,"67":1,"68":1},"2":{"7":5,"8":3,"9":3,"10":2,"11":4,"13":1,"15":3,"16":6,"17":6,"18":5,"20":2,"21":7,"26":3,"30":1,"32":2,"42":2,"54":1,"61":2,"66":3,"67":7,"68":2,"72":2,"75":2}}],["slowly",{"2":{"53":1}}],["src",{"2":{"42":4,"44":1,"45":11,"48":1,"50":3,"65":2,"70":1,"71":2,"72":2,"76":1}}],["scribendo",{"2":{"77":1}}],["scripts",{"2":{"46":1}}],["script",{"2":{"41":1,"43":1,"45":1}}],["scripting",{"2":{"39":1}}],["scope",{"2":{"14":2}}],["snippets",{"0":{"57":1},"2":{"57":1,"63":1}}],["snippet",{"2":{"37":1,"57":1}}],["specify",{"2":{"40":2,"42":2}}],["specified",{"2":{"40":2,"42":2}}],["specifies",{"2":{"39":1}}],["specifically",{"2":{"41":1}}],["specific",{"2":{"7":1,"14":1,"40":2,"42":2}}],["spend",{"2":{"38":1}}],["span",{"2":{"29":4,"61":8,"64":4,"76":1}}],["spaces",{"2":{"48":1,"50":2}}],["space",{"2":{"19":1,"21":1,"50":1}}],["systems",{"2":{"40":4,"41":1,"42":4}}],["system",{"2":{"18":1,"34":1,"38":1,"49":1}}],["syntax",{"0":{"68":1},"2":{"9":1,"10":1,"13":1,"37":1,"39":1,"54":2,"67":1,"68":3,"75":1}}],["small",{"2":{"17":1,"52":1}}],["share",{"2":{"57":1,"63":1}}],["sharing",{"0":{"57":1}}],["shame",{"2":{"17":1}}],["shell",{"2":{"35":2}}],["sh",{"2":{"35":4}}],["ship",{"2":{"32":1}}],["short",{"2":{"43":1,"63":1}}],["shorter",{"2":{"11":1,"68":1}}],["shorthand",{"2":{"3":1,"9":1,"13":1}}],["showed",{"2":{"65":1}}],["shows",{"2":{"36":1,"56":2}}],["showing",{"2":{"19":1}}],["show",{"2":{"8":1,"15":1,"56":1,"63":1}}],["shoulder",{"2":{"76":1}}],["shouldn",{"2":{"76":1}}],["should",{"2":{"6":1,"27":1,"36":1,"37":2,"39":1,"40":2,"42":1,"45":1,"49":1,"50":1,"53":2,"56":2,"66":1,"67":1,"73":3,"76":2}}],["store",{"2":{"57":1}}],["stop",{"2":{"50":2}}],["steps",{"2":{"48":1}}],["stuff",{"2":{"41":3}}],["studio",{"0":{"37":1},"2":{"34":1,"37":2}}],["styled",{"2":{"61":1,"73":1}}],["styles",{"2":{"61":5}}],["style",{"2":{"29":3,"31":1,"61":1}}],["style=styles",{"2":{"61":8}}],["style=",{"2":{"29":2,"61":2,"64":2}}],["styling",{"0":{"29":1},"2":{"29":1}}],["structure",{"0":{"47":1},"2":{"47":1,"65":1}}],["structured",{"2":{"39":1}}],["strive",{"2":{"67":1}}],["strictly",{"2":{"44":1}}],["strict",{"2":{"32":2}}],["strings",{"0":{"25":1},"2":{"13":1,"14":1,"22":1,"25":1}}],["string",{"0":{"6":1,"16":1,"25":1},"2":{"3":4,"4":9,"5":11,"6":9,"7":16,"8":8,"9":8,"10":6,"11":13,"14":2,"15":8,"16":8,"17":8,"18":4,"19":4,"21":10,"22":3,"25":2,"27":8,"28":8,"29":8,"57":1,"61":16,"64":8,"69":4,"70":4,"71":6,"72":2,"73":2,"74":1,"76":8}}],["straightforward",{"2":{"17":1}}],["still",{"2":{"17":2,"47":1}}],["states",{"2":{"76":1}}],["statements",{"2":{"32":1}}],["stable",{"2":{"40":2,"42":2}}],["stanzas",{"2":{"39":1,"40":3}}],["stanza",{"0":{"41":1},"2":{"39":2,"40":8,"41":2,"42":5,"46":1,"47":2,"48":1,"49":1}}],["standard",{"2":{"17":1,"40":2,"62":1}}],["started",{"2":{"57":1}}],["starter",{"0":{"36":1},"2":{"22":2,"39":1}}],["start",{"2":{"22":3,"26":2,"40":2,"42":2,"61":2,"65":1,"72":2}}],["starting",{"2":{"16":1}}],["stale",{"2":{"14":1}}],["sandwich|",{"2":{"72":2}}],["sandwiches",{"2":{"67":1}}],["sandwich",{"2":{"66":7,"67":4,"68":4,"76":6}}],["save",{"2":{"61":2,"75":1}}],["said",{"2":{"53":1}}],["safe",{"2":{"32":1}}],["safer",{"2":{"13":1}}],["says",{"2":{"58":1}}],["saying",{"2":{"40":2}}],["say",{"2":{"24":1,"41":1}}],["same",{"2":{"9":2,"13":2,"14":1,"27":1,"40":1,"47":1,"54":1,"58":2,"63":2,"65":1,"67":1,"71":1,"74":1}}],["sum",{"2":{"70":1}}],["summary",{"2":{"54":1}}],["superior",{"2":{"67":1}}],["support",{"2":{"34":1,"38":1,"54":1}}],["supply",{"2":{"13":1}}],["sustainable",{"2":{"29":1}}],["submodule",{"2":{"76":1}}],["subfolders",{"2":{"40":2}}],["subsystem",{"2":{"34":1}}],["substitute",{"2":{"21":1}}],["subtracts",{"2":{"12":1,"14":1}}],["surprised",{"2":{"59":1}}],["sure",{"2":{"16":1,"36":1,"42":1}}],["surrounded",{"2":{"4":1}}],["succinctly",{"2":{"26":1}}],["succeeded",{"2":{"35":1}}],["succeeds",{"2":{"16":1}}],["successfully",{"2":{"16":1,"36":1}}],["success",{"2":{"16":2}}],["such",{"2":{"13":1,"32":1,"34":1}}],["signed",{"2":{"64":1}}],["signature",{"2":{"16":1,"17":2,"73":1}}],["since",{"2":{"38":1,"67":1,"76":1}}],["single",{"2":{"11":2,"12":1,"14":1,"17":1,"23":1,"27":1,"44":1,"47":2,"54":1,"69":3,"70":2,"75":1}}],["sides",{"2":{"63":1}}],["side",{"2":{"22":1,"56":1}}],["simplify",{"2":{"67":1}}],["simplest",{"2":{"22":1,"35":1}}],["simple",{"2":{"9":1,"44":1}}],["similar",{"2":{"16":1,"17":1,"47":1,"76":1}}],["silent",{"2":{"12":1}}],["site",{"2":{"2":1}}],["solid",{"2":{"61":2}}],["solutions",{"0":{"14":1,"21":1,"32":1,"50":1,"64":1,"76":1}}],["somewhat",{"2":{"23":1}}],["somewhere",{"2":{"16":1}}],["some",{"2":{"16":7,"17":7,"18":6,"19":1,"21":19,"22":1,"26":5,"28":1,"31":1,"36":1,"42":2,"61":2,"72":2}}],["something",{"2":{"15":1,"35":1,"50":1,"56":1,"64":1,"76":2}}],["sources",{"2":{"40":2,"42":2}}],["source",{"2":{"14":1,"21":1,"27":1,"32":1,"50":1,"56":1,"57":1,"64":1,"76":1}}],["so",{"2":{"6":2,"9":1,"12":1,"14":1,"16":1,"27":1,"28":1,"43":1,"45":1,"47":1,"58":1,"67":1,"68":1,"71":1,"73":2,"76":1}}],["s",{"2":{"3":2,"4":2,"5":1,"6":1,"7":1,"9":2,"10":2,"11":1,"12":2,"14":1,"16":1,"17":2,"22":1,"23":1,"24":1,"27":2,"28":1,"29":1,"32":2,"35":1,"36":1,"39":6,"40":4,"42":2,"43":1,"44":3,"45":1,"47":2,"48":2,"50":2,"54":1,"55":1,"56":1,"57":1,"59":1,"60":1,"61":2,"62":1,"63":1,"64":1,"67":1,"68":3,"70":2,"73":2,"74":1,"75":3,"76":3}}],["separator",{"2":{"50":2}}],["separate",{"2":{"38":1,"47":1,"48":1,"50":1,"59":1,"63":1}}],["sense",{"2":{"38":1,"39":1,"66":1,"71":1}}],["several",{"2":{"38":1}}],["sets",{"2":{"44":1}}],["set",{"2":{"39":2,"73":2,"76":1}}],["settings",{"2":{"37":1}}],["setcounter",{"2":{"27":6,"29":4,"61":10,"64":6}}],["setcelsius",{"2":{"3":4,"4":4,"12":2,"14":4,"15":4}}],["search",{"2":{"37":1}}],["section",{"2":{"31":1,"46":1}}],["second",{"2":{"3":1,"17":1}}],["sequence",{"2":{"28":1}}],["seen",{"2":{"59":1}}],["seems",{"2":{"47":1}}],["see",{"2":{"10":1,"11":1,"14":2,"17":1,"18":1,"22":2,"25":1,"29":1,"32":1,"36":1,"37":1,"40":1,"41":2,"56":5,"71":2,"72":1,"73":3,"76":1}}],["seeing",{"2":{"6":1,"56":1}}],["serves",{"2":{"67":1}}],["served",{"2":{"45":1}}],["servegit",{"2":{"36":1}}],["server",{"2":{"22":1,"42":1,"45":3}}],["servemake",{"2":{"2":1,"45":1}}],["serve",{"2":{"2":2,"22":1,"36":2,"41":3,"42":7,"44":13,"45":11,"47":1,"48":1,"50":1,"72":1}}],["breakdown",{"2":{"44":1}}],["breaking",{"2":{"17":1}}],["browser",{"2":{"22":1,"36":1,"41":1,"45":1,"73":1}}],["browsing",{"2":{"17":1}}],["branches",{"2":{"9":1,"13":1,"67":1}}],["branch",{"2":{"7":1,"15":2,"16":4,"18":1,"19":1,"21":1,"30":1,"32":1,"66":1}}],["braces",{"2":{"4":2}}],["bind",{"2":{"73":1}}],["bindings",{"2":{"75":1}}],["binding",{"2":{"70":2,"73":1,"75":1}}],["binary",{"2":{"12":1,"14":1}}],["bit",{"2":{"8":1,"11":1,"14":1,"26":1,"29":1,"75":1}}],["b",{"2":{"9":2,"17":8,"71":2,"73":4}}],["blank",{"2":{"8":1}}],["burgers",{"2":{"67":1}}],["burger",{"2":{"66":6,"67":4,"68":4,"72":2,"76":6}}],["built",{"2":{"38":1}}],["building",{"2":{"41":2}}],["build",{"2":{"18":1,"22":1,"36":3,"38":1,"40":5,"41":6,"42":4,"43":1,"45":4,"47":2,"49":3,"53":1,"65":2}}],["bug",{"2":{"7":1,"12":1}}],["button",{"2":{"27":8,"29":8,"30":1,"61":24,"62":2,"64":8}}],["but",{"2":{"3":1,"8":1,"9":2,"11":2,"12":1,"16":1,"18":2,"22":1,"24":1,"30":1,"35":1,"39":1,"40":2,"41":1,"44":1,"45":1,"47":1,"54":1,"56":2,"58":2,"63":2,"65":1,"71":3,"73":2,"76":2}}],["bad",{"2":{"67":1}}],["baz",{"2":{"62":4}}],["bar",{"2":{"55":8,"56":14,"58":8,"60":5}}],["back",{"2":{"5":1,"18":1,"77":1}}],["bashwebpack",{"2":{"41":1}}],["bashgit",{"2":{"36":1}}],["bash",{"2":{"35":1}}],["bashbash",{"2":{"35":1}}],["bashmake",{"2":{"1":1,"2":1}}],["basics",{"2":{"53":1}}],["basically",{"2":{"32":1,"40":1,"44":1,"45":1}}],["basic",{"0":{"29":1},"2":{"31":1,"73":1}}],["based",{"2":{"5":1,"49":1,"52":1,"73":1}}],["by",{"2":{"4":2,"7":1,"8":1,"11":2,"14":1,"18":1,"19":1,"22":1,"27":1,"29":1,"36":1,"39":2,"40":5,"42":2,"45":2,"48":1,"56":4,"62":2,"64":1,"65":1,"75":2,"76":1}}],["bottom",{"2":{"56":2}}],["bother",{"2":{"18":1}}],["both",{"2":{"9":1,"52":1,"58":1,"60":1,"63":2,"75":1}}],["boilerplate",{"2":{"24":1}}],["boiling",{"2":{"18":1}}],["body",{"2":{"4":1,"68":1,"75":1}}],["book",{"0":{"0":1},"1":{"1":1,"2":1}}],["beautiful",{"2":{"53":1}}],["best",{"2":{"39":1}}],["besides",{"2":{"13":1,"40":1}}],["beverage",{"2":{"36":1}}],["begin",{"2":{"32":1}}],["between",{"2":{"18":1,"55":1}}],["better",{"2":{"15":1,"71":1,"76":1}}],["been",{"2":{"14":1,"38":1,"39":2,"65":1}}],["being",{"2":{"14":1,"23":1,"27":1,"40":2,"42":2,"66":1,"76":1}}],["becomes",{"2":{"11":1}}],["because",{"2":{"3":1,"9":1,"11":1,"15":1,"19":1,"27":1,"39":1,"47":1,"50":1,"52":1,"54":2,"59":1,"61":1,"66":1,"71":1}}],["before",{"2":{"8":1,"40":2,"42":2,"44":1}}],["beware",{"2":{"3":1}}],["be",{"2":{"3":1,"4":2,"7":2,"8":1,"13":1,"14":2,"16":2,"17":2,"21":1,"22":1,"23":1,"28":1,"31":1,"32":2,"37":1,"39":1,"40":2,"41":1,"42":2,"43":1,"44":1,"45":1,"49":1,"50":3,"53":1,"54":1,"56":1,"59":1,"63":1,"64":1,"65":3,"66":2,"67":2,"70":1,"73":1,"74":1,"76":2}}]],"serializationVersion":2}';export{e as default}; diff --git a/assets/chunks/VPLocalSearchBox.004b014b.js b/assets/chunks/VPLocalSearchBox.004b014b.js new file mode 100644 index 00000000..bdbaeefe --- /dev/null +++ b/assets/chunks/VPLocalSearchBox.004b014b.js @@ -0,0 +1,7 @@ +import{X as pt,h as ie,x as Be,ah as kt,ai as Nt,d as It,E as be,aj as et,g as we,ak as Dt,al as _t,y as Ot,am as Rt,j as De,O as de,V as xe,an as Mt,S as Lt,U as Pt,ao as zt,Y as Bt,s as Vt,ap as $t,o as X,b as Wt,k as F,a1 as jt,l as U,aq as Kt,ar as Jt,as as Ut,c as te,n as tt,e as Fe,D as rt,F as nt,a as he,t as ve,at as Ht,p as Gt,m as Qt,au as at,av as qt,a6 as Yt,ac as Zt,_ as Xt}from"./framework.0e8ae64e.js";import{u as er,c as tr}from"./theme.802a1aee.js";const rr={root:()=>pt(()=>import("./@localSearchIndexroot.ae053162.js"),[])};/*! +* tabbable 6.2.0 +* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE +*/var mt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Ae=mt.join(","),yt=typeof Element>"u",se=yt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Ce=!yt&&Element.prototype.getRootNode?function(o){var e;return o==null||(e=o.getRootNode)===null||e===void 0?void 0:e.call(o)}:function(o){return o==null?void 0:o.ownerDocument},Te=function o(e,t){var r;t===void 0&&(t=!0);var a=e==null||(r=e.getAttribute)===null||r===void 0?void 0:r.call(e,"inert"),n=a===""||a==="true",i=n||t&&e&&o(e.parentNode);return i},nr=function(e){var t,r=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return r===""||r==="true"},gt=function(e,t,r){if(Te(e))return[];var a=Array.prototype.slice.apply(e.querySelectorAll(Ae));return t&&se.call(e,Ae)&&a.unshift(e),a=a.filter(r),a},bt=function o(e,t,r){for(var a=[],n=Array.from(e);n.length;){var i=n.shift();if(!Te(i,!1))if(i.tagName==="SLOT"){var s=i.assignedElements(),u=s.length?s:i.children,l=o(u,!0,r);r.flatten?a.push.apply(a,l):a.push({scopeParent:i,candidates:l})}else{var d=se.call(i,Ae);d&&r.filter(i)&&(t||!e.includes(i))&&a.push(i);var h=i.shadowRoot||typeof r.getShadowRoot=="function"&&r.getShadowRoot(i),v=!Te(h,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(i));if(h&&v){var y=o(h===!0?i.children:h.children,!0,r);r.flatten?a.push.apply(a,y):a.push({scopeParent:i,candidates:y})}else n.unshift.apply(n,i.children)}}return a},wt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},oe=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||nr(e))&&!wt(e)?0:e.tabIndex},ar=function(e,t){var r=oe(e);return r<0&&t&&!wt(e)?0:r},ir=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},xt=function(e){return e.tagName==="INPUT"},or=function(e){return xt(e)&&e.type==="hidden"},sr=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(r){return r.tagName==="SUMMARY"});return t},ur=function(e,t){for(var r=0;rsummary:first-of-type"),i=n?e.parentElement:e;if(se.call(i,"details:not([open]) *"))return!0;if(!r||r==="full"||r==="legacy-full"){if(typeof a=="function"){for(var s=e;e;){var u=e.parentElement,l=Ce(e);if(u&&!u.shadowRoot&&a(u)===!0)return it(e);e.assignedSlot?e=e.assignedSlot:!u&&l!==e.ownerDocument?e=l.host:e=u}e=s}if(dr(e))return!e.getClientRects().length;if(r!=="legacy-full")return!0}else if(r==="non-zero-area")return it(e);return!1},vr=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var r=0;r=0)},mr=function o(e){var t=[],r=[];return e.forEach(function(a,n){var i=!!a.scopeParent,s=i?a.scopeParent:a,u=ar(s,i),l=i?o(a.candidates):s;u===0?i?t.push.apply(t,l):t.push(s):r.push({documentOrder:n,tabIndex:u,item:a,isScope:i,content:l})}),r.sort(ir).reduce(function(a,n){return n.isScope?a.push.apply(a,n.content):a.push(n.content),a},[]).concat(t)},yr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=bt([e],t.includeContainer,{filter:Ve.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:pr}):r=gt(e,t.includeContainer,Ve.bind(null,t)),mr(r)},gr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=bt([e],t.includeContainer,{filter:ke.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):r=gt(e,t.includeContainer,ke.bind(null,t)),r},ue=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return se.call(e,Ae)===!1?!1:Ve(t,e)},br=mt.concat("iframe").join(","),_e=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return se.call(e,br)===!1?!1:ke(t,e)};/*! +* focus-trap 7.5.4 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/function ot(o,e){var t=Object.keys(o);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(o);e&&(r=r.filter(function(a){return Object.getOwnPropertyDescriptor(o,a).enumerable})),t.push.apply(t,r)}return t}function st(o){for(var e=1;e0){var r=e[e.length-1];r!==t&&r.pause()}var a=e.indexOf(t);a===-1||e.splice(a,1),e.push(t)},deactivateTrap:function(e,t){var r=e.indexOf(t);r!==-1&&e.splice(r,1),e.length>0&&e[e.length-1].unpause()}},Er=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},Sr=function(e){return(e==null?void 0:e.key)==="Escape"||(e==null?void 0:e.key)==="Esc"||(e==null?void 0:e.keyCode)===27},ye=function(e){return(e==null?void 0:e.key)==="Tab"||(e==null?void 0:e.keyCode)===9},Ar=function(e){return ye(e)&&!e.shiftKey},Cr=function(e){return ye(e)&&e.shiftKey},lt=function(e){return setTimeout(e,0)},ct=function(e,t){var r=-1;return e.every(function(a,n){return t(a)?(r=n,!1):!0}),r},pe=function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),a=1;a1?p-1:0),k=1;k=0)c=r.activeElement;else{var f=i.tabbableGroups[0],p=f&&f.firstTabbableNode;c=p||d("fallbackFocus")}if(!c)throw new Error("Your focus-trap needs to have at least one focusable element");return c},v=function(){if(i.containerGroups=i.containers.map(function(c){var f=yr(c,n.tabbableOptions),p=gr(c,n.tabbableOptions),N=f.length>0?f[0]:void 0,k=f.length>0?f[f.length-1]:void 0,M=p.find(function(w){return ue(w)}),z=p.slice().reverse().find(function(w){return ue(w)}),m=!!f.find(function(w){return oe(w)>0});return{container:c,tabbableNodes:f,focusableNodes:p,posTabIndexesFound:m,firstTabbableNode:N,lastTabbableNode:k,firstDomTabbableNode:M,lastDomTabbableNode:z,nextTabbableNode:function(B){var G=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,j=f.indexOf(B);return j<0?G?p.slice(p.indexOf(B)+1).find(function(K){return ue(K)}):p.slice(0,p.indexOf(B)).reverse().find(function(K){return ue(K)}):f[j+(G?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(c){return c.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!d("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(c){return c.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},y=function x(c){var f=c.activeElement;if(f)return f.shadowRoot&&f.shadowRoot.activeElement!==null?x(f.shadowRoot):f},b=function x(c){if(c!==!1&&c!==y(document)){if(!c||!c.focus){x(h());return}c.focus({preventScroll:!!n.preventScroll}),i.mostRecentlyFocusedNode=c,Er(c)&&c.select()}},E=function(c){var f=d("setReturnFocus",c);return f||(f===!1?!1:c)},g=function(c){var f=c.target,p=c.event,N=c.isBackward,k=N===void 0?!1:N;f=f||Ee(p),v();var M=null;if(i.tabbableGroups.length>0){var z=l(f,p),m=z>=0?i.containerGroups[z]:void 0;if(z<0)k?M=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:M=i.tabbableGroups[0].firstTabbableNode;else if(k){var w=ct(i.tabbableGroups,function(J){var Q=J.firstTabbableNode;return f===Q});if(w<0&&(m.container===f||_e(f,n.tabbableOptions)&&!ue(f,n.tabbableOptions)&&!m.nextTabbableNode(f,!1))&&(w=z),w>=0){var B=w===0?i.tabbableGroups.length-1:w-1,G=i.tabbableGroups[B];M=oe(f)>=0?G.lastTabbableNode:G.lastDomTabbableNode}else ye(p)||(M=m.nextTabbableNode(f,!1))}else{var j=ct(i.tabbableGroups,function(J){var Q=J.lastTabbableNode;return f===Q});if(j<0&&(m.container===f||_e(f,n.tabbableOptions)&&!ue(f,n.tabbableOptions)&&!m.nextTabbableNode(f))&&(j=z),j>=0){var K=j===i.tabbableGroups.length-1?0:j+1,V=i.tabbableGroups[K];M=oe(f)>=0?V.firstTabbableNode:V.firstDomTabbableNode}else ye(p)||(M=m.nextTabbableNode(f))}}else M=d("fallbackFocus");return M},S=function(c){var f=Ee(c);if(!(l(f,c)>=0)){if(pe(n.clickOutsideDeactivates,c)){s.deactivate({returnFocus:n.returnFocusOnDeactivate});return}pe(n.allowOutsideClick,c)||c.preventDefault()}},T=function(c){var f=Ee(c),p=l(f,c)>=0;if(p||f instanceof Document)p&&(i.mostRecentlyFocusedNode=f);else{c.stopImmediatePropagation();var N,k=!0;if(i.mostRecentlyFocusedNode)if(oe(i.mostRecentlyFocusedNode)>0){var M=l(i.mostRecentlyFocusedNode),z=i.containerGroups[M].tabbableNodes;if(z.length>0){var m=z.findIndex(function(w){return w===i.mostRecentlyFocusedNode});m>=0&&(n.isKeyForward(i.recentNavEvent)?m+1=0&&(N=z[m-1],k=!1))}}else i.containerGroups.some(function(w){return w.tabbableNodes.some(function(B){return oe(B)>0})})||(k=!1);else k=!1;k&&(N=g({target:i.mostRecentlyFocusedNode,isBackward:n.isKeyBackward(i.recentNavEvent)})),b(N||i.mostRecentlyFocusedNode||h())}i.recentNavEvent=void 0},C=function(c){var f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;i.recentNavEvent=c;var p=g({event:c,isBackward:f});p&&(ye(c)&&c.preventDefault(),b(p))},R=function(c){if(Sr(c)&&pe(n.escapeDeactivates,c)!==!1){c.preventDefault(),s.deactivate();return}(n.isKeyForward(c)||n.isKeyBackward(c))&&C(c,n.isKeyBackward(c))},L=function(c){var f=Ee(c);l(f,c)>=0||pe(n.clickOutsideDeactivates,c)||pe(n.allowOutsideClick,c)||(c.preventDefault(),c.stopImmediatePropagation())},P=function(){if(i.active)return ut.activateTrap(a,s),i.delayInitialFocusTimer=n.delayInitialFocus?lt(function(){b(h())}):b(h()),r.addEventListener("focusin",T,!0),r.addEventListener("mousedown",S,{capture:!0,passive:!1}),r.addEventListener("touchstart",S,{capture:!0,passive:!1}),r.addEventListener("click",L,{capture:!0,passive:!1}),r.addEventListener("keydown",R,{capture:!0,passive:!1}),s},I=function(){if(i.active)return r.removeEventListener("focusin",T,!0),r.removeEventListener("mousedown",S,!0),r.removeEventListener("touchstart",S,!0),r.removeEventListener("click",L,!0),r.removeEventListener("keydown",R,!0),s},A=function(c){var f=c.some(function(p){var N=Array.from(p.removedNodes);return N.some(function(k){return k===i.mostRecentlyFocusedNode})});f&&b(h())},_=typeof window<"u"&&"MutationObserver"in window?new MutationObserver(A):void 0,O=function(){_&&(_.disconnect(),i.active&&!i.paused&&i.containers.map(function(c){_.observe(c,{subtree:!0,childList:!0})}))};return s={get active(){return i.active},get paused(){return i.paused},activate:function(c){if(i.active)return this;var f=u(c,"onActivate"),p=u(c,"onPostActivate"),N=u(c,"checkCanFocusTrap");N||v(),i.active=!0,i.paused=!1,i.nodeFocusedBeforeActivation=r.activeElement,f==null||f();var k=function(){N&&v(),P(),O(),p==null||p()};return N?(N(i.containers.concat()).then(k,k),this):(k(),this)},deactivate:function(c){if(!i.active)return this;var f=st({onDeactivate:n.onDeactivate,onPostDeactivate:n.onPostDeactivate,checkCanReturnFocus:n.checkCanReturnFocus},c);clearTimeout(i.delayInitialFocusTimer),i.delayInitialFocusTimer=void 0,I(),i.active=!1,i.paused=!1,O(),ut.deactivateTrap(a,s);var p=u(f,"onDeactivate"),N=u(f,"onPostDeactivate"),k=u(f,"checkCanReturnFocus"),M=u(f,"returnFocus","returnFocusOnDeactivate");p==null||p();var z=function(){lt(function(){M&&b(E(i.nodeFocusedBeforeActivation)),N==null||N()})};return M&&k?(k(E(i.nodeFocusedBeforeActivation)).then(z,z),this):(z(),this)},pause:function(c){if(i.paused||!i.active)return this;var f=u(c,"onPause"),p=u(c,"onPostPause");return i.paused=!0,f==null||f(),I(),O(),p==null||p(),this},unpause:function(c){if(!i.paused||!i.active)return this;var f=u(c,"onUnpause"),p=u(c,"onPostUnpause");return i.paused=!1,f==null||f(),v(),P(),O(),p==null||p(),this},updateContainerElements:function(c){var f=[].concat(c).filter(Boolean);return i.containers=f.map(function(p){return typeof p=="string"?r.querySelector(p):p}),i.active&&v(),O(),this}},s.updateContainerElements(e),s};function Nr(o,e={}){let t;const{immediate:r,...a}=e,n=ie(!1),i=ie(!1),s=h=>t&&t.activate(h),u=h=>t&&t.deactivate(h),l=()=>{t&&(t.pause(),i.value=!0)},d=()=>{t&&(t.unpause(),i.value=!1)};return Be(()=>kt(o),h=>{h&&(t=kr(h,{...a,onActivate(){n.value=!0,e.onActivate&&e.onActivate()},onDeactivate(){n.value=!1,e.onDeactivate&&e.onDeactivate()}}),r&&s())},{flush:"post"}),Nt(()=>u()),{hasFocus:n,isPaused:i,activate:s,deactivate:u,pause:l,unpause:d}}class ce{constructor(e,t=!0,r=[],a=5e3){this.ctx=e,this.iframes=t,this.exclude=r,this.iframesTimeout=a}static matches(e,t){const r=typeof t=="string"?[t]:t,a=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(a){let n=!1;return r.every(i=>a.call(e,i)?(n=!0,!1):!0),n}else return!1}getContexts(){let e,t=[];return typeof this.ctx>"u"||!this.ctx?e=[]:NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?e=this.ctx:typeof this.ctx=="string"?e=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):e=[this.ctx],e.forEach(r=>{const a=t.filter(n=>n.contains(r)).length>0;t.indexOf(r)===-1&&!a&&t.push(r)}),t}getIframeContents(e,t,r=()=>{}){let a;try{const n=e.contentWindow;if(a=n.document,!n||!a)throw new Error("iframe inaccessible")}catch{r()}a&&t(a)}isIframeBlank(e){const t="about:blank",r=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&r!==t&&r}observeIframeLoad(e,t,r){let a=!1,n=null;const i=()=>{if(!a){a=!0,clearTimeout(n);try{this.isIframeBlank(e)||(e.removeEventListener("load",i),this.getIframeContents(e,t,r))}catch{r()}}};e.addEventListener("load",i),n=setTimeout(i,this.iframesTimeout)}onIframeReady(e,t,r){try{e.contentWindow.document.readyState==="complete"?this.isIframeBlank(e)?this.observeIframeLoad(e,t,r):this.getIframeContents(e,t,r):this.observeIframeLoad(e,t,r)}catch{r()}}waitForIframes(e,t){let r=0;this.forEachIframe(e,()=>!0,a=>{r++,this.waitForIframes(a.querySelector("html"),()=>{--r||t()})},a=>{a||t()})}forEachIframe(e,t,r,a=()=>{}){let n=e.querySelectorAll("iframe"),i=n.length,s=0;n=Array.prototype.slice.call(n);const u=()=>{--i<=0&&a(s)};i||u(),n.forEach(l=>{ce.matches(l,this.exclude)?u():this.onIframeReady(l,d=>{t(l)&&(s++,r(d)),u()},u)})}createIterator(e,t,r){return document.createNodeIterator(e,t,r,!1)}createInstanceOnIframe(e){return new ce(e.querySelector("html"),this.iframes)}compareNodeIframe(e,t,r){const a=e.compareDocumentPosition(r),n=Node.DOCUMENT_POSITION_PRECEDING;if(a&n)if(t!==null){const i=t.compareDocumentPosition(r),s=Node.DOCUMENT_POSITION_FOLLOWING;if(i&s)return!0}else return!0;return!1}getIteratorNode(e){const t=e.previousNode();let r;return t===null?r=e.nextNode():r=e.nextNode()&&e.nextNode(),{prevNode:t,node:r}}checkIframeFilter(e,t,r,a){let n=!1,i=!1;return a.forEach((s,u)=>{s.val===r&&(n=u,i=s.handled)}),this.compareNodeIframe(e,t,r)?(n===!1&&!i?a.push({val:r,handled:!0}):n!==!1&&!i&&(a[n].handled=!0),!0):(n===!1&&a.push({val:r,handled:!1}),!1)}handleOpenIframes(e,t,r,a){e.forEach(n=>{n.handled||this.getIframeContents(n.val,i=>{this.createInstanceOnIframe(i).forEachNode(t,r,a)})})}iterateThroughNodes(e,t,r,a,n){const i=this.createIterator(t,e,a);let s=[],u=[],l,d,h=()=>({prevNode:d,node:l}=this.getIteratorNode(i),l);for(;h();)this.iframes&&this.forEachIframe(t,v=>this.checkIframeFilter(l,d,v,s),v=>{this.createInstanceOnIframe(v).forEachNode(e,y=>u.push(y),a)}),u.push(l);u.forEach(v=>{r(v)}),this.iframes&&this.handleOpenIframes(s,e,r,a),n()}forEachNode(e,t,r,a=()=>{}){const n=this.getContexts();let i=n.length;i||a(),n.forEach(s=>{const u=()=>{this.iterateThroughNodes(e,s,t,r,()=>{--i<=0&&a()})};this.iframes?this.waitForIframes(s,u):u()})}}let Ir=class{constructor(e){this.ctx=e,this.ie=!1;const t=window.navigator.userAgent;(t.indexOf("MSIE")>-1||t.indexOf("Trident")>-1)&&(this.ie=!0)}set opt(e){this._opt=Object.assign({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:()=>{},noMatch:()=>{},filter:()=>!0,done:()=>{},debug:!1,log:window.console},e)}get opt(){return this._opt}get iterator(){return new ce(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}log(e,t="debug"){const r=this.opt.log;this.opt.debug&&typeof r=="object"&&typeof r[t]=="function"&&r[t](`mark.js: ${e}`)}escapeStr(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}createRegExp(e){return this.opt.wildcards!=="disabled"&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),this.opt.wildcards!=="disabled"&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),e}createSynonymsRegExp(e){const t=this.opt.synonyms,r=this.opt.caseSensitive?"":"i",a=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(let n in t)if(t.hasOwnProperty(n)){const i=t[n],s=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(n):this.escapeStr(n),u=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(i):this.escapeStr(i);s!==""&&u!==""&&(e=e.replace(new RegExp(`(${this.escapeStr(s)}|${this.escapeStr(u)})`,`gm${r}`),a+`(${this.processSynomyms(s)}|${this.processSynomyms(u)})`+a))}return e}processSynomyms(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}setupWildcardsRegExp(e){return e=e.replace(/(?:\\)*\?/g,t=>t.charAt(0)==="\\"?"?":""),e.replace(/(?:\\)*\*/g,t=>t.charAt(0)==="\\"?"*":"")}createWildcardsRegExp(e){let t=this.opt.wildcards==="withSpaces";return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}setupIgnoreJoinersRegExp(e){return e.replace(/[^(|)\\]/g,(t,r,a)=>{let n=a.charAt(r+1);return/[(|)\\]/.test(n)||n===""?t:t+"\0"})}createJoinersRegExp(e){let t=[];const r=this.opt.ignorePunctuation;return Array.isArray(r)&&r.length&&t.push(this.escapeStr(r.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join(`[${t.join("")}]*`):e}createDiacriticsRegExp(e){const t=this.opt.caseSensitive?"":"i",r=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"];let a=[];return e.split("").forEach(n=>{r.every(i=>{if(i.indexOf(n)!==-1){if(a.indexOf(i)>-1)return!1;e=e.replace(new RegExp(`[${i}]`,`gm${t}`),`[${i}]`),a.push(i)}return!0})}),e}createMergedBlanksRegExp(e){return e.replace(/[\s]+/gmi,"[\\s]+")}createAccuracyRegExp(e){const t="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";let r=this.opt.accuracy,a=typeof r=="string"?r:r.value,n=typeof r=="string"?[]:r.limiters,i="";switch(n.forEach(s=>{i+=`|${this.escapeStr(s)}`}),a){case"partially":default:return`()(${e})`;case"complementary":return i="\\s"+(i||this.escapeStr(t)),`()([^${i}]*${e}[^${i}]*)`;case"exactly":return`(^|\\s${i})(${e})(?=$|\\s${i})`}}getSeparatedKeywords(e){let t=[];return e.forEach(r=>{this.opt.separateWordSearch?r.split(" ").forEach(a=>{a.trim()&&t.indexOf(a)===-1&&t.push(a)}):r.trim()&&t.indexOf(r)===-1&&t.push(r)}),{keywords:t.sort((r,a)=>a.length-r.length),length:t.length}}isNumeric(e){return Number(parseFloat(e))==e}checkRanges(e){if(!Array.isArray(e)||Object.prototype.toString.call(e[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];const t=[];let r=0;return e.sort((a,n)=>a.start-n.start).forEach(a=>{let{start:n,end:i,valid:s}=this.callNoMatchOnInvalidRanges(a,r);s&&(a.start=n,a.length=i-n,t.push(a),r=i)}),t}callNoMatchOnInvalidRanges(e,t){let r,a,n=!1;return e&&typeof e.start<"u"?(r=parseInt(e.start,10),a=r+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&a-t>0&&a-r>0?n=!0:(this.log(`Ignoring invalid or overlapping range: ${JSON.stringify(e)}`),this.opt.noMatch(e))):(this.log(`Ignoring invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)),{start:r,end:a,valid:n}}checkWhitespaceRanges(e,t,r){let a,n=!0,i=r.length,s=t-i,u=parseInt(e.start,10)-s;return u=u>i?i:u,a=u+parseInt(e.length,10),a>i&&(a=i,this.log(`End range automatically set to the max value of ${i}`)),u<0||a-u<0||u>i||a>i?(n=!1,this.log(`Invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)):r.substring(u,a).replace(/\s+/g,"")===""&&(n=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:u,end:a,valid:n}}getTextNodes(e){let t="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,a=>{r.push({start:t.length,end:(t+=a.textContent).length,node:a})},a=>this.matchesExclude(a.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT,()=>{e({value:t,nodes:r})})}matchesExclude(e){return ce.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}wrapRangeInTextNode(e,t,r){const a=this.opt.element?this.opt.element:"mark",n=e.splitText(t),i=n.splitText(r-t);let s=document.createElement(a);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=n.textContent,n.parentNode.replaceChild(s,n),i}wrapRangeInMappedTextNode(e,t,r,a,n){e.nodes.every((i,s)=>{const u=e.nodes[s+1];if(typeof u>"u"||u.start>t){if(!a(i.node))return!1;const l=t-i.start,d=(r>i.end?i.end:r)-i.start,h=e.value.substr(0,i.start),v=e.value.substr(d+i.start);if(i.node=this.wrapRangeInTextNode(i.node,l,d),e.value=h+v,e.nodes.forEach((y,b)=>{b>=s&&(e.nodes[b].start>0&&b!==s&&(e.nodes[b].start-=d),e.nodes[b].end-=d)}),r-=d,n(i.node.previousSibling,i.start),r>i.end)t=i.end;else return!1}return!0})}wrapMatches(e,t,r,a,n){const i=t===0?0:t+1;this.getTextNodes(s=>{s.nodes.forEach(u=>{u=u.node;let l;for(;(l=e.exec(u.textContent))!==null&&l[i]!=="";){if(!r(l[i],u))continue;let d=l.index;if(i!==0)for(let h=1;h{let u;for(;(u=e.exec(s.value))!==null&&u[i]!=="";){let l=u.index;if(i!==0)for(let h=1;hr(u[i],h),(h,v)=>{e.lastIndex=v,a(h)})}n()})}wrapRangeFromIndex(e,t,r,a){this.getTextNodes(n=>{const i=n.value.length;e.forEach((s,u)=>{let{start:l,end:d,valid:h}=this.checkWhitespaceRanges(s,i,n.value);h&&this.wrapRangeInMappedTextNode(n,l,d,v=>t(v,s,n.value.substring(l,d),u),v=>{r(v,s)})}),a()})}unwrapMatches(e){const t=e.parentNode;let r=document.createDocumentFragment();for(;e.firstChild;)r.appendChild(e.removeChild(e.firstChild));t.replaceChild(r,e),this.ie?this.normalizeTextNode(t):t.normalize()}normalizeTextNode(e){if(e){if(e.nodeType===3)for(;e.nextSibling&&e.nextSibling.nodeType===3;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}markRegExp(e,t){this.opt=t,this.log(`Searching with expression "${e}"`);let r=0,a="wrapMatches";const n=i=>{r++,this.opt.each(i)};this.opt.acrossElements&&(a="wrapMatchesAcrossElements"),this[a](e,this.opt.ignoreGroups,(i,s)=>this.opt.filter(s,i,r),n,()=>{r===0&&this.opt.noMatch(e),this.opt.done(r)})}mark(e,t){this.opt=t;let r=0,a="wrapMatches";const{keywords:n,length:i}=this.getSeparatedKeywords(typeof e=="string"?[e]:e),s=this.opt.caseSensitive?"":"i",u=l=>{let d=new RegExp(this.createRegExp(l),`gm${s}`),h=0;this.log(`Searching with expression "${d}"`),this[a](d,1,(v,y)=>this.opt.filter(y,l,r,h),v=>{h++,r++,this.opt.each(v)},()=>{h===0&&this.opt.noMatch(l),n[i-1]===l?this.opt.done(r):u(n[n.indexOf(l)+1])})};this.opt.acrossElements&&(a="wrapMatchesAcrossElements"),i===0?this.opt.done(r):u(n[0])}markRanges(e,t){this.opt=t;let r=0,a=this.checkRanges(e);a&&a.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(a)),this.wrapRangeFromIndex(a,(n,i,s,u)=>this.opt.filter(n,i,s,u),(n,i)=>{r++,this.opt.each(n,i)},()=>{this.opt.done(r)})):this.opt.done(r)}unmark(e){this.opt=e;let t=this.opt.element?this.opt.element:"*";t+="[data-markjs]",this.opt.className&&(t+=`.${this.opt.className}`),this.log(`Removal selector "${t}"`),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,r=>{this.unwrapMatches(r)},r=>{const a=ce.matches(r,t),n=this.matchesExclude(r);return!a||n?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}};function Dr(o){const e=new Ir(o);return this.mark=(t,r)=>(e.mark(t,r),this),this.markRegExp=(t,r)=>(e.markRegExp(t,r),this),this.markRanges=(t,r)=>(e.markRanges(t,r),this),this.unmark=t=>(e.unmark(t),this),this}var $=function(){return $=Object.assign||function(e){for(var t,r=1,a=arguments.length;r0&&n[n.length-1])&&(l[0]===6||l[0]===2)){t=0;continue}if(l[0]===3&&(!n||l[1]>n[0]&&l[1]=o.length&&(o=void 0),{value:o&&o[r++],done:!o}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(o,e){var t=typeof Symbol=="function"&&o[Symbol.iterator];if(!t)return o;var r=t.call(o),a,n=[],i;try{for(;(e===void 0||e-- >0)&&!(a=r.next()).done;)n.push(a.value)}catch(s){i={error:s}}finally{try{a&&!a.done&&(t=r.return)&&t.call(r)}finally{if(i)throw i.error}}return n}var Rr="ENTRIES",Ft="KEYS",Et="VALUES",H="",Oe=function(){function o(e,t){var r=e._tree,a=Array.from(r.keys());this.set=e,this._type=t,this._path=a.length>0?[{node:r,keys:a}]:[]}return o.prototype.next=function(){var e=this.dive();return this.backtrack(),e},o.prototype.dive=function(){if(this._path.length===0)return{done:!0,value:void 0};var e=le(this._path),t=e.node,r=e.keys;if(le(r)===H)return{done:!1,value:this.result()};var a=t.get(le(r));return this._path.push({node:a,keys:Array.from(a.keys())}),this.dive()},o.prototype.backtrack=function(){if(this._path.length!==0){var e=le(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}},o.prototype.key=function(){return this.set._prefix+this._path.map(function(e){var t=e.keys;return le(t)}).filter(function(e){return e!==H}).join("")},o.prototype.value=function(){return le(this._path).node.get(H)},o.prototype.result=function(){switch(this._type){case Et:return this.value();case Ft:return this.key();default:return[this.key(),this.value()]}},o.prototype[Symbol.iterator]=function(){return this},o}(),le=function(o){return o[o.length-1]},Mr=function(o,e,t){var r=new Map;if(e===void 0)return r;for(var a=e.length+1,n=a+t,i=new Uint8Array(n*a).fill(t+1),s=0;st)continue e}St(o.get(y),e,t,r,a,E,i,s+y)}}}catch(f){u={error:f}}finally{try{v&&!v.done&&(l=h.return)&&l.call(h)}finally{if(u)throw u.error}}},Re=function(){function o(e,t){e===void 0&&(e=new Map),t===void 0&&(t=""),this._size=void 0,this._tree=e,this._prefix=t}return o.prototype.atPrefix=function(e){var t,r;if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");var a=W(Ne(this._tree,e.slice(this._prefix.length)),2),n=a[0],i=a[1];if(n===void 0){var s=W(Ke(i),2),u=s[0],l=s[1];try{for(var d=D(u.keys()),h=d.next();!h.done;h=d.next()){var v=h.value;if(v!==H&&v.startsWith(l)){var y=new Map;return y.set(v.slice(l.length),u.get(v)),new o(y,e)}}}catch(b){t={error:b}}finally{try{h&&!h.done&&(r=d.return)&&r.call(d)}finally{if(t)throw t.error}}}return new o(n,e)},o.prototype.clear=function(){this._size=void 0,this._tree.clear()},o.prototype.delete=function(e){return this._size=void 0,Lr(this._tree,e)},o.prototype.entries=function(){return new Oe(this,Rr)},o.prototype.forEach=function(e){var t,r;try{for(var a=D(this),n=a.next();!n.done;n=a.next()){var i=W(n.value,2),s=i[0],u=i[1];e(s,u,this)}}catch(l){t={error:l}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}},o.prototype.fuzzyGet=function(e,t){return Mr(this._tree,e,t)},o.prototype.get=function(e){var t=$e(this._tree,e);return t!==void 0?t.get(H):void 0},o.prototype.has=function(e){var t=$e(this._tree,e);return t!==void 0&&t.has(H)},o.prototype.keys=function(){return new Oe(this,Ft)},o.prototype.set=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Me(this._tree,e);return r.set(H,t),this},Object.defineProperty(o.prototype,"size",{get:function(){if(this._size)return this._size;this._size=0;for(var e=this.entries();!e.next().done;)this._size+=1;return this._size},enumerable:!1,configurable:!0}),o.prototype.update=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Me(this._tree,e);return r.set(H,t(r.get(H))),this},o.prototype.fetch=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Me(this._tree,e),a=r.get(H);return a===void 0&&r.set(H,a=t()),a},o.prototype.values=function(){return new Oe(this,Et)},o.prototype[Symbol.iterator]=function(){return this.entries()},o.from=function(e){var t,r,a=new o;try{for(var n=D(e),i=n.next();!i.done;i=n.next()){var s=W(i.value,2),u=s[0],l=s[1];a.set(u,l)}}catch(d){t={error:d}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}return a},o.fromObject=function(e){return o.from(Object.entries(e))},o}(),Ne=function(o,e,t){var r,a;if(t===void 0&&(t=[]),e.length===0||o==null)return[o,t];try{for(var n=D(o.keys()),i=n.next();!i.done;i=n.next()){var s=i.value;if(s!==H&&e.startsWith(s))return t.push([o,s]),Ne(o.get(s),e.slice(s.length),t)}}catch(u){r={error:u}}finally{try{i&&!i.done&&(a=n.return)&&a.call(n)}finally{if(r)throw r.error}}return t.push([o,e]),Ne(void 0,"",t)},$e=function(o,e){var t,r;if(e.length===0||o==null)return o;try{for(var a=D(o.keys()),n=a.next();!n.done;n=a.next()){var i=n.value;if(i!==H&&e.startsWith(i))return $e(o.get(i),e.slice(i.length))}}catch(s){t={error:s}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}},Me=function(o,e){var t,r,a=e.length;e:for(var n=0;o&&n0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new Re,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}},o.prototype.discard=function(e){var t=this,r=this._idToShortId.get(e);if(r==null)throw new Error("MiniSearch: cannot discard document with ID ".concat(e,": it is not in the index"));this._idToShortId.delete(e),this._documentIds.delete(r),this._storedFields.delete(r),(this._fieldLength.get(r)||[]).forEach(function(a,n){t.removeFieldLength(r,n,t._documentCount,a)}),this._fieldLength.delete(r),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()},o.prototype.maybeAutoVacuum=function(){if(this._options.autoVacuum!==!1){var e=this._options.autoVacuum,t=e.minDirtFactor,r=e.minDirtCount,a=e.batchSize,n=e.batchWait;this.conditionalVacuum({batchSize:a,batchWait:n},{minDirtCount:r,minDirtFactor:t})}},o.prototype.discardAll=function(e){var t,r,a=this._options.autoVacuum;try{this._options.autoVacuum=!1;try{for(var n=D(e),i=n.next();!i.done;i=n.next()){var s=i.value;this.discard(s)}}catch(u){t={error:u}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}}finally{this._options.autoVacuum=a}this.maybeAutoVacuum()},o.prototype.replace=function(e){var t=this._options,r=t.idField,a=t.extractField,n=a(e,r);this.discard(n),this.add(e)},o.prototype.vacuum=function(e){return e===void 0&&(e={}),this.conditionalVacuum(e)},o.prototype.conditionalVacuum=function(e,t){var r=this;return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(function(){var a=r._enqueuedVacuumConditions;return r._enqueuedVacuumConditions=je,r.performVacuuming(e,a)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)},o.prototype.performVacuuming=function(e,t){return _r(this,void 0,void 0,function(){var r,a,n,i,s,u,l,d,h,v,y,b,E,g,S,T,C,R,L,P,I,A,_,O,x;return Or(this,function(c){switch(c.label){case 0:if(r=this._dirtCount,!this.vacuumConditionsMet(t))return[3,10];a=e.batchSize||We.batchSize,n=e.batchWait||We.batchWait,i=1,c.label=1;case 1:c.trys.push([1,7,8,9]),s=D(this._index),u=s.next(),c.label=2;case 2:if(u.done)return[3,6];l=W(u.value,2),d=l[0],h=l[1];try{for(v=(A=void 0,D(h)),y=v.next();!y.done;y=v.next()){b=W(y.value,2),E=b[0],g=b[1];try{for(S=(O=void 0,D(g)),T=S.next();!T.done;T=S.next())C=W(T.value,1),R=C[0],!this._documentIds.has(R)&&(g.size<=1?h.delete(E):g.delete(R))}catch(f){O={error:f}}finally{try{T&&!T.done&&(x=S.return)&&x.call(S)}finally{if(O)throw O.error}}}}catch(f){A={error:f}}finally{try{y&&!y.done&&(_=v.return)&&_.call(v)}finally{if(A)throw A.error}}return this._index.get(d).size===0&&this._index.delete(d),i%a!==0?[3,4]:[4,new Promise(function(f){return setTimeout(f,n)})];case 3:c.sent(),c.label=4;case 4:i+=1,c.label=5;case 5:return u=s.next(),[3,2];case 6:return[3,9];case 7:return L=c.sent(),P={error:L},[3,9];case 8:try{u&&!u.done&&(I=s.return)&&I.call(s)}finally{if(P)throw P.error}return[7];case 9:this._dirtCount-=r,c.label=10;case 10:return[4,null];case 11:return c.sent(),this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null,[2]}})})},o.prototype.vacuumConditionsMet=function(e){if(e==null)return!0;var t=e.minDirtCount,r=e.minDirtFactor;return t=t||ze.minDirtCount,r=r||ze.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=r},Object.defineProperty(o.prototype,"isVacuuming",{get:function(){return this._currentVacuum!=null},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtCount",{get:function(){return this._dirtCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtFactor",{get:function(){return this._dirtCount/(1+this._documentCount+this._dirtCount)},enumerable:!1,configurable:!0}),o.prototype.has=function(e){return this._idToShortId.has(e)},o.prototype.getStoredFields=function(e){var t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)},o.prototype.search=function(e,t){var r,a;t===void 0&&(t={});var n=this.executeQuery(e,t),i=[];try{for(var s=D(n),u=s.next();!u.done;u=s.next()){var l=W(u.value,2),d=l[0],h=l[1],v=h.score,y=h.terms,b=h.match,E=y.length||1,g={id:this._documentIds.get(d),score:v*E,terms:Object.keys(b),match:b};Object.assign(g,this._storedFields.get(d)),(t.filter==null||t.filter(g))&&i.push(g)}}catch(S){r={error:S}}finally{try{u&&!u.done&&(a=s.return)&&a.call(s)}finally{if(r)throw r.error}}return e===o.wildcard&&t.boostDocument==null&&this._options.searchOptions.boostDocument==null||i.sort(ht),i},o.prototype.autoSuggest=function(e,t){var r,a,n,i;t===void 0&&(t={}),t=$($({},this._options.autoSuggestOptions),t);var s=new Map;try{for(var u=D(this.search(e,t)),l=u.next();!l.done;l=u.next()){var d=l.value,h=d.score,v=d.terms,y=v.join(" "),b=s.get(y);b!=null?(b.score+=h,b.count+=1):s.set(y,{score:h,terms:v,count:1})}}catch(L){r={error:L}}finally{try{l&&!l.done&&(a=u.return)&&a.call(u)}finally{if(r)throw r.error}}var E=[];try{for(var g=D(s),S=g.next();!S.done;S=g.next()){var T=W(S.value,2),b=T[0],C=T[1],h=C.score,v=C.terms,R=C.count;E.push({suggestion:b,terms:v,score:h/R})}}catch(L){n={error:L}}finally{try{S&&!S.done&&(i=g.return)&&i.call(g)}finally{if(n)throw n.error}}return E.sort(ht),E},Object.defineProperty(o.prototype,"documentCount",{get:function(){return this._documentCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"termCount",{get:function(){return this._index.size},enumerable:!1,configurable:!0}),o.loadJSON=function(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)},o.getDefault=function(e){if(Pe.hasOwnProperty(e))return Le(Pe,e);throw new Error('MiniSearch: unknown option "'.concat(e,'"'))},o.loadJS=function(e,t){var r,a,n,i,s,u,l=e.index,d=e.documentCount,h=e.nextId,v=e.documentIds,y=e.fieldIds,b=e.fieldLength,E=e.averageFieldLength,g=e.storedFields,S=e.dirtCount,T=e.serializationVersion;if(T!==1&&T!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");var C=new o(t);C._documentCount=d,C._nextId=h,C._documentIds=Se(v),C._idToShortId=new Map,C._fieldIds=y,C._fieldLength=Se(b),C._avgFieldLength=E,C._storedFields=Se(g),C._dirtCount=S||0,C._index=new Re;try{for(var R=D(C._documentIds),L=R.next();!L.done;L=R.next()){var P=W(L.value,2),I=P[0],A=P[1];C._idToShortId.set(A,I)}}catch(m){r={error:m}}finally{try{L&&!L.done&&(a=R.return)&&a.call(R)}finally{if(r)throw r.error}}try{for(var _=D(l),O=_.next();!O.done;O=_.next()){var x=W(O.value,2),c=x[0],f=x[1],p=new Map;try{for(var N=(s=void 0,D(Object.keys(f))),k=N.next();!k.done;k=N.next()){var M=k.value,z=f[M];T===1&&(z=z.ds),p.set(parseInt(M,10),Se(z))}}catch(m){s={error:m}}finally{try{k&&!k.done&&(u=N.return)&&u.call(N)}finally{if(s)throw s.error}}C._index.set(c,p)}}catch(m){n={error:m}}finally{try{O&&!O.done&&(i=_.return)&&i.call(_)}finally{if(n)throw n.error}}return C},o.prototype.executeQuery=function(e,t){var r=this;if(t===void 0&&(t={}),e===o.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){var a=$($($({},t),e),{queries:void 0}),n=e.queries.map(function(g){return r.executeQuery(g,a)});return this.combineResults(n,a.combineWith)}var i=this._options,s=i.tokenize,u=i.processTerm,l=i.searchOptions,d=$($({tokenize:s,processTerm:u},l),t),h=d.tokenize,v=d.processTerm,y=h(e).flatMap(function(g){return v(g)}).filter(function(g){return!!g}),b=y.map(Wr(d)),E=b.map(function(g){return r.executeQuerySpec(g,d)});return this.combineResults(E,d.combineWith)},o.prototype.executeQuerySpec=function(e,t){var r,a,n,i,s=$($({},this._options.searchOptions),t),u=(s.fields||this._options.fields).reduce(function(M,z){var m;return $($({},M),(m={},m[z]=Le(s.boost,z)||1,m))},{}),l=s.boostDocument,d=s.weights,h=s.maxFuzzy,v=s.bm25,y=$($({},ft.weights),d),b=y.fuzzy,E=y.prefix,g=this._index.get(e.term),S=this.termResults(e.term,e.term,1,g,u,l,v),T,C;if(e.prefix&&(T=this._index.atPrefix(e.term)),e.fuzzy){var R=e.fuzzy===!0?.2:e.fuzzy,L=R<1?Math.min(h,Math.round(e.term.length*R)):R;L&&(C=this._index.fuzzyGet(e.term,L))}if(T)try{for(var P=D(T),I=P.next();!I.done;I=P.next()){var A=W(I.value,2),_=A[0],O=A[1],x=_.length-e.term.length;if(x){C==null||C.delete(_);var c=E*_.length/(_.length+.3*x);this.termResults(e.term,_,c,O,u,l,v,S)}}}catch(M){r={error:M}}finally{try{I&&!I.done&&(a=P.return)&&a.call(P)}finally{if(r)throw r.error}}if(C)try{for(var f=D(C.keys()),p=f.next();!p.done;p=f.next()){var _=p.value,N=W(C.get(_),2),k=N[0],x=N[1];if(x){var c=b*_.length/(_.length+x);this.termResults(e.term,_,c,k,u,l,v,S)}}}catch(M){n={error:M}}finally{try{p&&!p.done&&(i=f.return)&&i.call(f)}finally{if(n)throw n.error}}return S},o.prototype.executeWildcardQuery=function(e){var t,r,a=new Map,n=$($({},this._options.searchOptions),e);try{for(var i=D(this._documentIds),s=i.next();!s.done;s=i.next()){var u=W(s.value,2),l=u[0],d=u[1],h=n.boostDocument?n.boostDocument(d,"",this._storedFields.get(l)):1;a.set(l,{score:h,terms:[],match:{}})}}catch(v){t={error:v}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return a},o.prototype.combineResults=function(e,t){if(t===void 0&&(t=Je),e.length===0)return new Map;var r=t.toLowerCase();return e.reduce(Br[r])||new Map},o.prototype.toJSON=function(){var e,t,r,a,n=[];try{for(var i=D(this._index),s=i.next();!s.done;s=i.next()){var u=W(s.value,2),l=u[0],d=u[1],h={};try{for(var v=(r=void 0,D(d)),y=v.next();!y.done;y=v.next()){var b=W(y.value,2),E=b[0],g=b[1];h[E]=Object.fromEntries(g)}}catch(S){r={error:S}}finally{try{y&&!y.done&&(a=v.return)&&a.call(v)}finally{if(r)throw r.error}}n.push([l,h])}}catch(S){e={error:S}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:n,serializationVersion:2}},o.prototype.termResults=function(e,t,r,a,n,i,s,u){var l,d,h,v,y;if(u===void 0&&(u=new Map),a==null)return u;try{for(var b=D(Object.keys(n)),E=b.next();!E.done;E=b.next()){var g=E.value,S=n[g],T=this._fieldIds[g],C=a.get(T);if(C!=null){var R=C.size,L=this._avgFieldLength[T];try{for(var P=(h=void 0,D(C.keys())),I=P.next();!I.done;I=P.next()){var A=I.value;if(!this._documentIds.has(A)){this.removeTerm(T,A,t),R-=1;continue}var _=i?i(this._documentIds.get(A),t,this._storedFields.get(A)):1;if(_){var O=C.get(A),x=this._fieldLength.get(A)[T],c=$r(O,R,this._documentCount,x,L,s),f=r*S*_*c,p=u.get(A);if(p){p.score+=f,Kr(p.terms,e);var N=Le(p.match,t);N?N.push(g):p.match[t]=[g]}else u.set(A,{score:f,terms:[e],match:(y={},y[t]=[g],y)})}}}catch(k){h={error:k}}finally{try{I&&!I.done&&(v=P.return)&&v.call(P)}finally{if(h)throw h.error}}}}}catch(k){l={error:k}}finally{try{E&&!E.done&&(d=b.return)&&d.call(b)}finally{if(l)throw l.error}}return u},o.prototype.addTerm=function(e,t,r){var a=this._index.fetch(r,vt),n=a.get(e);if(n==null)n=new Map,n.set(t,1),a.set(e,n);else{var i=n.get(t);n.set(t,(i||0)+1)}},o.prototype.removeTerm=function(e,t,r){if(!this._index.has(r)){this.warnDocumentChanged(t,e,r);return}var a=this._index.fetch(r,vt),n=a.get(e);n==null||n.get(t)==null?this.warnDocumentChanged(t,e,r):n.get(t)<=1?n.size<=1?a.delete(e):n.delete(t):n.set(t,n.get(t)-1),this._index.get(r).size===0&&this._index.delete(r)},o.prototype.warnDocumentChanged=function(e,t,r){var a,n;try{for(var i=D(Object.keys(this._fieldIds)),s=i.next();!s.done;s=i.next()){var u=s.value;if(this._fieldIds[u]===t){this._options.logger("warn","MiniSearch: document with ID ".concat(this._documentIds.get(e),' has changed before removal: term "').concat(r,'" was not present in field "').concat(u,'". Removing a document after it has changed can corrupt the index!'),"version_conflict");return}}}catch(l){a={error:l}}finally{try{s&&!s.done&&(n=i.return)&&n.call(i)}finally{if(a)throw a.error}}},o.prototype.addDocumentId=function(e){var t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t},o.prototype.addFields=function(e){for(var t=0;t(Gt("data-v-2813d7e3"),o=o(),Qt(),o),Ur=["aria-owns"],Hr={class:"shell"},Gr=["title"],Qr=Y(()=>F("svg",{class:"search-icon",width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[F("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2"},[F("circle",{cx:"11",cy:"11",r:"8"}),F("path",{d:"m21 21l-4.35-4.35"})])],-1)),qr=[Qr],Yr={class:"search-actions before"},Zr=["title"],Xr=Y(()=>F("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 12H5m7 7l-7-7l7-7"})],-1)),en=[Xr],tn=["placeholder"],rn={class:"search-actions"},nn=["title"],an=Y(()=>F("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M3 14h7v7H3zM3 3h7v7H3zm11 1h7m-7 5h7m-7 6h7m-7 5h7"})],-1)),on=[an],sn=["disabled","title"],un=Y(()=>F("svg",{width:"18",height:"18",viewBox:"0 0 24 24","aria-hidden":"true"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"})],-1)),ln=[un],cn=["id","role","aria-labelledby"],fn=["aria-selected"],dn=["href","aria-label","onMouseenter","onFocusin"],hn={class:"titles"},vn=Y(()=>F("span",{class:"title-icon"},"#",-1)),pn=["innerHTML"],mn=Y(()=>F("svg",{width:"18",height:"18",viewBox:"0 0 24 24"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"m9 18l6-6l-6-6"})],-1)),yn={class:"title main"},gn=["innerHTML"],bn={key:0,class:"excerpt-wrapper"},wn={key:0,class:"excerpt",inert:""},xn=["innerHTML"],Fn=Y(()=>F("div",{class:"excerpt-gradient-bottom"},null,-1)),En=Y(()=>F("div",{class:"excerpt-gradient-top"},null,-1)),Sn={key:0,class:"no-results"},An={class:"search-keyboard-shortcuts"},Cn=["aria-label"],Tn=Y(()=>F("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 19V5m-7 7l7-7l7 7"})],-1)),kn=[Tn],Nn=["aria-label"],In=Y(()=>F("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[F("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 5v14m7-7l-7 7l-7-7"})],-1)),Dn=[In],_n=["aria-label"],On=Y(()=>F("svg",{width:"14",height:"14",viewBox:"0 0 24 24"},[F("g",{fill:"none",stroke:"currentcolor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2"},[F("path",{d:"m9 10l-5 5l5 5"}),F("path",{d:"M20 4v7a4 4 0 0 1-4 4H4"})])],-1)),Rn=[On],Mn=["aria-label"],Ln=It({__name:"VPLocalSearchBox",emits:["close"],setup(o,{emit:e}){var M,z;const t=e,r=be(),a=be(),n=be(rr),i=er(),{activate:s}=Nr(r,{immediate:!0,allowOutsideClick:!0,clickOutsideDeactivates:!0,escapeDeactivates:!0}),{localeIndex:u,theme:l}=i,d=et(async()=>{var m,w,B,G,j,K,V,J,Q;return at(zr.loadJSON((B=await((w=(m=n.value)[u.value])==null?void 0:w.call(m)))==null?void 0:B.default,{fields:["title","titles","text"],storeFields:["title","titles"],searchOptions:{fuzzy:.2,prefix:!0,boost:{title:4,text:2,titles:1},...((G=l.value.search)==null?void 0:G.provider)==="local"&&((K=(j=l.value.search.options)==null?void 0:j.miniSearch)==null?void 0:K.searchOptions)},...((V=l.value.search)==null?void 0:V.provider)==="local"&&((Q=(J=l.value.search.options)==null?void 0:J.miniSearch)==null?void 0:Q.options)}))}),v=we(()=>{var m,w;return((m=l.value.search)==null?void 0:m.provider)==="local"&&((w=l.value.search.options)==null?void 0:w.disableQueryPersistence)===!0}).value?ie(""):Dt("vitepress:local-search-filter",""),y=_t("vitepress:local-search-detailed-list",((M=l.value.search)==null?void 0:M.provider)==="local"&&((z=l.value.search.options)==null?void 0:z.detailedView)===!0),b=we(()=>{var m,w,B;return((m=l.value.search)==null?void 0:m.provider)==="local"&&(((w=l.value.search.options)==null?void 0:w.disableDetailedView)===!0||((B=l.value.search.options)==null?void 0:B.detailedView)===!1)}),E=we(()=>{var w,B,G,j,K,V,J;const m=((w=l.value.search)==null?void 0:w.options)??l.value.algolia;return((K=(j=(G=(B=m==null?void 0:m.locales)==null?void 0:B[u.value])==null?void 0:G.translations)==null?void 0:j.button)==null?void 0:K.buttonText)||((J=(V=m==null?void 0:m.translations)==null?void 0:V.button)==null?void 0:J.buttonText)||"Search"});Ot(()=>{b.value&&(y.value=!1)});const g=be([]),S=ie(!1);Be(v,()=>{S.value=!1});const T=et(async()=>{if(a.value)return at(new Dr(a.value))},null);Rt(()=>[d.value,v.value,y.value],async([m,w,B],G,j)=>{var Ue,He,Ge,Qe;let K=!1;if(j(()=>{K=!0}),!m)return;g.value=m.search(w).slice(0,16),S.value=!0;const V=B?await Promise.all(g.value.map(q=>C(q.id))):[];if(K)return;const J=new Map;for(const{id:q,mod:re}of V){const ne=q.slice(0,q.indexOf("#"));let ee=J.get(ne);if(ee)continue;ee=new Map,J.set(ne,ee);const Z=re.default??re;if(Z!=null&&Z.render||Z!=null&&Z.setup){const ae=qt(Z);ae.config.warnHandler=()=>{},ae.provide(Yt,i),Object.defineProperties(ae.config.globalProperties,{$frontmatter:{get(){return i.frontmatter.value}},$params:{get(){return i.page.value.params}}});const qe=document.createElement("div");ae.mount(qe),qe.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(fe=>{var Xe;const ge=(Xe=fe.querySelector("a"))==null?void 0:Xe.getAttribute("href"),Ye=(ge==null?void 0:ge.startsWith("#"))&&ge.slice(1);if(!Ye)return;let Ze="";for(;(fe=fe.nextElementSibling)&&!/^h[1-6]$/i.test(fe.tagName);)Ze+=fe.outerHTML;ee.set(Ye,Ze)}),ae.unmount()}if(K)return}const Q=new Set;if(g.value=g.value.map(q=>{const[re,ne]=q.id.split("#"),ee=J.get(re),Z=(ee==null?void 0:ee.get(ne))??"";for(const ae in q.match)Q.add(ae);return{...q,text:Z}}),await de(),K)return;await new Promise(q=>{var re;(re=T.value)==null||re.unmark({done:()=>{var ne;(ne=T.value)==null||ne.markRegExp(k(Q),{done:q})}})});const Ie=((Ue=r.value)==null?void 0:Ue.querySelectorAll(".result .excerpt"))??[];for(const q of Ie)(He=q.querySelector('mark[data-markjs="true"]'))==null||He.scrollIntoView({block:"center"});(Qe=(Ge=a.value)==null?void 0:Ge.firstElementChild)==null||Qe.scrollIntoView({block:"start"})},{debounce:200,immediate:!0});async function C(m){const w=Zt(m.slice(0,m.indexOf("#")));try{if(!w)throw new Error(`Cannot find file for id: ${m}`);return{id:m,mod:await pt(()=>import(w),[])}}catch(B){return console.error(B),{id:m,mod:{}}}}const R=ie(),L=we(()=>{var m;return((m=v.value)==null?void 0:m.length)<=0});function P(m=!0){var w,B;(w=R.value)==null||w.focus(),m&&((B=R.value)==null||B.select())}De(()=>{P()});function I(m){m.pointerType==="mouse"&&P()}const A=ie(-1),_=ie(!1);Be(g,m=>{A.value=m.length?0:-1,O()});function O(){de(()=>{const m=document.querySelector(".result.selected");m&&m.scrollIntoView({block:"nearest"})})}xe("ArrowUp",m=>{m.preventDefault(),A.value--,A.value<0&&(A.value=g.value.length-1),_.value=!0,O()}),xe("ArrowDown",m=>{m.preventDefault(),A.value++,A.value>=g.value.length&&(A.value=0),_.value=!0,O()});const x=Mt();xe("Enter",m=>{if(m.target instanceof HTMLButtonElement&&m.target.type!=="submit")return;const w=g.value[A.value];if(m.target instanceof HTMLInputElement&&!w){m.preventDefault();return}w&&(x.go(w.id),t("close"))}),xe("Escape",()=>{t("close")});const c={modal:{displayDetails:"Display detailed list",resetButtonTitle:"Reset search",backButtonTitle:"Close search",noResultsText:"No results for",footer:{selectText:"to select",selectKeyAriaLabel:"enter",navigateText:"to navigate",navigateUpKeyAriaLabel:"up arrow",navigateDownKeyAriaLabel:"down arrow",closeText:"to close",closeKeyAriaLabel:"escape"}}},f=Lt(tr)(Pt(()=>{var m;return(m=l.value.search)==null?void 0:m.options}),c);De(()=>{window.history.pushState(null,"",null)}),zt("popstate",m=>{m.preventDefault(),t("close")});const p=Bt(Vt?document.body:null);De(()=>{de(()=>{p.value=!0,de().then(()=>s())})}),$t(()=>{p.value=!1});function N(){v.value="",de().then(()=>P(!1))}function k(m){return new RegExp([...m].sort((w,B)=>B.length-w.length).map(w=>`(${w.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")})`).join("|"),"gi")}return(m,w)=>{var B,G,j,K;return X(),Wt(Ht,{to:"body"},[F("div",{ref_key:"el",ref:r,role:"button","aria-owns":(B=g.value)!=null&&B.length?"localsearch-list":void 0,"aria-expanded":"true","aria-haspopup":"listbox","aria-labelledby":"localsearch-label",class:"VPLocalSearchBox"},[F("div",{class:"backdrop",onClick:w[0]||(w[0]=V=>m.$emit("close"))}),F("div",Hr,[F("form",{class:"search-bar",onPointerup:w[4]||(w[4]=V=>I(V)),onSubmit:w[5]||(w[5]=jt(()=>{},["prevent"]))},[F("label",{title:E.value,id:"localsearch-label",for:"localsearch-input"},qr,8,Gr),F("div",Yr,[F("button",{class:"back-button",title:U(f)("modal.backButtonTitle"),onClick:w[1]||(w[1]=V=>m.$emit("close"))},en,8,Zr)]),Kt(F("input",{ref_key:"searchInput",ref:R,"onUpdate:modelValue":w[2]||(w[2]=V=>Ut(v)?v.value=V:null),placeholder:E.value,id:"localsearch-input","aria-labelledby":"localsearch-label",class:"search-input"},null,8,tn),[[Jt,U(v)]]),F("div",rn,[b.value?Fe("",!0):(X(),te("button",{key:0,class:tt(["toggle-layout-button",{"detailed-list":U(y)}]),type:"button",title:U(f)("modal.displayDetails"),onClick:w[3]||(w[3]=V=>A.value>-1&&(y.value=!U(y)))},on,10,nn)),F("button",{class:"clear-button",type:"reset",disabled:L.value,title:U(f)("modal.resetButtonTitle"),onClick:N},ln,8,sn)])],32),F("ul",{ref_key:"resultsEl",ref:a,id:(G=g.value)!=null&&G.length?"localsearch-list":void 0,role:(j=g.value)!=null&&j.length?"listbox":void 0,"aria-labelledby":(K=g.value)!=null&&K.length?"localsearch-label":void 0,class:"results",onMousemove:w[7]||(w[7]=V=>_.value=!1)},[(X(!0),te(nt,null,rt(g.value,(V,J)=>(X(),te("li",{key:V.id,role:"option","aria-selected":A.value===J?"true":"false"},[F("a",{href:V.id,class:tt(["result",{selected:A.value===J}]),"aria-label":[...V.titles,V.title].join(" > "),onMouseenter:Q=>!_.value&&(A.value=J),onFocusin:Q=>A.value=J,onClick:w[6]||(w[6]=Q=>m.$emit("close"))},[F("div",null,[F("div",hn,[vn,(X(!0),te(nt,null,rt(V.titles,(Q,Ie)=>(X(),te("span",{key:Ie,class:"title"},[F("span",{class:"text",innerHTML:Q},null,8,pn),mn]))),128)),F("span",yn,[F("span",{class:"text",innerHTML:V.title},null,8,gn)])]),U(y)?(X(),te("div",bn,[V.text?(X(),te("div",wn,[F("div",{class:"vp-doc",innerHTML:V.text},null,8,xn)])):Fe("",!0),Fn,En])):Fe("",!0)])],42,dn)],8,fn))),128)),U(v)&&!g.value.length&&S.value?(X(),te("li",Sn,[he(ve(U(f)("modal.noResultsText"))+' "',1),F("strong",null,ve(U(v)),1),he('" ')])):Fe("",!0)],40,cn),F("div",An,[F("span",null,[F("kbd",{"aria-label":U(f)("modal.footer.navigateUpKeyAriaLabel")},kn,8,Cn),F("kbd",{"aria-label":U(f)("modal.footer.navigateDownKeyAriaLabel")},Dn,8,Nn),he(" "+ve(U(f)("modal.footer.navigateText")),1)]),F("span",null,[F("kbd",{"aria-label":U(f)("modal.footer.selectKeyAriaLabel")},Rn,8,_n),he(" "+ve(U(f)("modal.footer.selectText")),1)]),F("span",null,[F("kbd",{"aria-label":U(f)("modal.footer.closeKeyAriaLabel")},"esc",8,Mn),he(" "+ve(U(f)("modal.footer.closeText")),1)])])])],8,Ur)])}}});const $n=Xt(Ln,[["__scopeId","data-v-2813d7e3"]]);export{$n as default}; diff --git a/assets/chunks/framework.0e8ae64e.js b/assets/chunks/framework.0e8ae64e.js new file mode 100644 index 00000000..8d74ade6 --- /dev/null +++ b/assets/chunks/framework.0e8ae64e.js @@ -0,0 +1,2 @@ +function mr(e,t){const n=Object.create(null),r=e.split(",");for(let s=0;s!!n[s.toLowerCase()]:s=>!!n[s]}const te={},mt=[],Oe=()=>{},di=()=>!1,hi=/^on[^a-z]/,zt=e=>hi.test(e),yr=e=>e.startsWith("onUpdate:"),ue=Object.assign,_r=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},pi=Object.prototype.hasOwnProperty,X=(e,t)=>pi.call(e,t),U=Array.isArray,yt=e=>An(e)==="[object Map]",Vs=e=>An(e)==="[object Set]",W=e=>typeof e=="function",ne=e=>typeof e=="string",Tn=e=>typeof e=="symbol",ee=e=>e!==null&&typeof e=="object",qs=e=>(ee(e)||W(e))&&W(e.then)&&W(e.catch),zs=Object.prototype.toString,An=e=>zs.call(e),gi=e=>An(e).slice(8,-1),Ys=e=>An(e)==="[object Object]",br=e=>ne(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,It=mr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Sn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},mi=/-(\w)/g,Ne=Sn(e=>e.replace(mi,(t,n)=>n?n.toUpperCase():"")),yi=/\B([A-Z])/g,ft=Sn(e=>e.replace(yi,"-$1").toLowerCase()),Rn=Sn(e=>e.charAt(0).toUpperCase()+e.slice(1)),dn=Sn(e=>e?`on${Rn(e)}`:""),ut=(e,t)=>!Object.is(e,t),hn=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},er=e=>{const t=parseFloat(e);return isNaN(t)?e:t},_i=e=>{const t=ne(e)?Number(e):NaN;return isNaN(t)?e:t};let Yr;const tr=()=>Yr||(Yr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function vr(e){if(U(e)){const t={};for(let n=0;n{if(n){const r=n.split(vi);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function wr(e){let t="";if(ne(e))t=e;else if(U(e))for(let n=0;nne(e)?e:e==null?"":U(e)||ee(e)&&(e.toString===zs||!W(e.toString))?JSON.stringify(e,Xs,2):String(e),Xs=(e,t)=>t&&t.__v_isRef?Xs(e,t.value):yt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s])=>(n[`${r} =>`]=s,n),{})}:Vs(t)?{[`Set(${t.size})`]:[...t.values()]}:ee(t)&&!U(t)&&!Ys(t)?String(t):t;let be;class Ti{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=be,!t&&be&&(this.index=(be.scopes||(be.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=be;try{return be=this,t()}finally{be=n}}}on(){be=this}off(){be=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},Zs=e=>(e.w&Qe)>0,Gs=e=>(e.n&Qe)>0,Ri=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r{(f==="length"||!Tn(f)&&f>=c)&&l.push(a)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":U(e)?br(n)&&l.push(i.get("length")):(l.push(i.get(lt)),yt(e)&&l.push(i.get(rr)));break;case"delete":U(e)||(l.push(i.get(lt)),yt(e)&&l.push(i.get(rr)));break;case"set":yt(e)&&l.push(i.get(lt));break}if(l.length===1)l[0]&&sr(l[0]);else{const c=[];for(const a of l)a&&c.push(...a);sr(Cr(c))}}function sr(e,t){const n=U(e)?e:[...e];for(const r of n)r.computed&&Xr(r);for(const r of n)r.computed||Xr(r)}function Xr(e,t){(e!==Se||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function Pi(e,t){var n;return(n=yn.get(e))==null?void 0:n.get(t)}const Mi=mr("__proto__,__v_isRef,__isVue"),no=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Tn)),Qr=Fi();function Fi(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=Q(this);for(let o=0,i=this.length;o{e[t]=function(...n){At();const r=Q(this)[t].apply(this,n);return St(),r}}),e}function Ii(e){const t=Q(this);return ye(t,"has",e),t.hasOwnProperty(e)}class ro{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const s=this._isReadonly,o=this._shallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw"&&r===(s?o?qi:lo:o?io:oo).get(t))return t;const i=U(t);if(!s){if(i&&X(Qr,n))return Reflect.get(Qr,n,r);if(n==="hasOwnProperty")return Ii}const l=Reflect.get(t,n,r);return(Tn(n)?no.has(n):Mi(n))||(s||ye(t,"get",n),o)?l:ce(l)?i&&br(n)?l:l.value:ee(l)?s?Mn(l):Pn(l):l}}class so extends ro{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];if(Ct(o)&&ce(o)&&!ce(r))return!1;if(!this._shallow&&(!_n(r)&&!Ct(r)&&(o=Q(o),r=Q(r)),!U(t)&&ce(o)&&!ce(r)))return o.value=r,!0;const i=U(t)&&br(n)?Number(n)e,On=e=>Reflect.getPrototypeOf(e);function Zt(e,t,n=!1,r=!1){e=e.__v_raw;const s=Q(e),o=Q(t);n||(ut(t,o)&&ye(s,"get",t),ye(s,"get",o));const{has:i}=On(s),l=r?xr:n?Sr:Bt;if(i.call(s,t))return l(e.get(t));if(i.call(s,o))return l(e.get(o));e!==s&&e.get(t)}function Gt(e,t=!1){const n=this.__v_raw,r=Q(n),s=Q(e);return t||(ut(e,s)&&ye(r,"has",e),ye(r,"has",s)),e===s?n.has(e):n.has(e)||n.has(s)}function en(e,t=!1){return e=e.__v_raw,!t&&ye(Q(e),"iterate",lt),Reflect.get(e,"size",e)}function Zr(e){e=Q(e);const t=Q(this);return On(t).has.call(t,e)||(t.add(e),De(t,"add",e,e)),this}function Gr(e,t){t=Q(t);const n=Q(this),{has:r,get:s}=On(n);let o=r.call(n,e);o||(e=Q(e),o=r.call(n,e));const i=s.call(n,e);return n.set(e,t),o?ut(t,i)&&De(n,"set",e,t):De(n,"add",e,t),this}function es(e){const t=Q(this),{has:n,get:r}=On(t);let s=n.call(t,e);s||(e=Q(e),s=n.call(t,e)),r&&r.call(t,e);const o=t.delete(e);return s&&De(t,"delete",e,void 0),o}function ts(){const e=Q(this),t=e.size!==0,n=e.clear();return t&&De(e,"clear",void 0,void 0),n}function tn(e,t){return function(r,s){const o=this,i=o.__v_raw,l=Q(i),c=t?xr:e?Sr:Bt;return!e&&ye(l,"iterate",lt),i.forEach((a,f)=>r.call(s,c(a),c(f),o))}}function nn(e,t,n){return function(...r){const s=this.__v_raw,o=Q(s),i=yt(o),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,a=s[e](...r),f=n?xr:t?Sr:Bt;return!t&&ye(o,"iterate",c?rr:lt),{next(){const{value:h,done:m}=a.next();return m?{value:h,done:m}:{value:l?[f(h[0]),f(h[1])]:f(h),done:m}},[Symbol.iterator](){return this}}}}function Ue(e){return function(...t){return e==="delete"?!1:this}}function ji(){const e={get(o){return Zt(this,o)},get size(){return en(this)},has:Gt,add:Zr,set:Gr,delete:es,clear:ts,forEach:tn(!1,!1)},t={get(o){return Zt(this,o,!1,!0)},get size(){return en(this)},has:Gt,add:Zr,set:Gr,delete:es,clear:ts,forEach:tn(!1,!0)},n={get(o){return Zt(this,o,!0)},get size(){return en(this,!0)},has(o){return Gt.call(this,o,!0)},add:Ue("add"),set:Ue("set"),delete:Ue("delete"),clear:Ue("clear"),forEach:tn(!0,!1)},r={get(o){return Zt(this,o,!0,!0)},get size(){return en(this,!0)},has(o){return Gt.call(this,o,!0)},add:Ue("add"),set:Ue("set"),delete:Ue("delete"),clear:Ue("clear"),forEach:tn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=nn(o,!1,!1),n[o]=nn(o,!0,!1),t[o]=nn(o,!1,!0),r[o]=nn(o,!0,!0)}),[e,n,t,r]}const[Di,Bi,ki,Ui]=ji();function Tr(e,t){const n=t?e?Ui:ki:e?Bi:Di;return(r,s,o)=>s==="__v_isReactive"?!e:s==="__v_isReadonly"?e:s==="__v_raw"?r:Reflect.get(X(n,s)&&s in r?n:r,s,o)}const Ki={get:Tr(!1,!1)},Wi={get:Tr(!1,!0)},Vi={get:Tr(!0,!1)},oo=new WeakMap,io=new WeakMap,lo=new WeakMap,qi=new WeakMap;function zi(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Yi(e){return e.__v_skip||!Object.isExtensible(e)?0:zi(gi(e))}function Pn(e){return Ct(e)?e:Ar(e,!1,Ni,Ki,oo)}function Ji(e){return Ar(e,!1,$i,Wi,io)}function Mn(e){return Ar(e,!0,Hi,Vi,lo)}function Ar(e,t,n,r,s){if(!ee(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=s.get(e);if(o)return o;const i=Yi(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return s.set(e,l),l}function _t(e){return Ct(e)?_t(e.__v_raw):!!(e&&e.__v_isReactive)}function Ct(e){return!!(e&&e.__v_isReadonly)}function _n(e){return!!(e&&e.__v_isShallow)}function co(e){return _t(e)||Ct(e)}function Q(e){const t=e&&e.__v_raw;return t?Q(t):e}function Lt(e){return mn(e,"__v_skip",!0),e}const Bt=e=>ee(e)?Pn(e):e,Sr=e=>ee(e)?Mn(e):e;function Rr(e){Ye&&Se&&(e=Q(e),to(e.dep||(e.dep=Cr())))}function Or(e,t){e=Q(e);const n=e.dep;n&&sr(n)}function ce(e){return!!(e&&e.__v_isRef===!0)}function ae(e){return ao(e,!1)}function Pr(e){return ao(e,!0)}function ao(e,t){return ce(e)?e:new Xi(e,t)}class Xi{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:Q(t),this._value=n?t:Bt(t)}get value(){return Rr(this),this._value}set value(t){const n=this.__v_isShallow||_n(t)||Ct(t);t=n?t:Q(t),ut(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Bt(t),Or(this))}}function Mr(e){return ce(e)?e.value:e}const Qi={get:(e,t,n)=>Mr(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const s=e[t];return ce(s)&&!ce(n)?(s.value=n,!0):Reflect.set(e,t,n,r)}};function uo(e){return _t(e)?e:new Proxy(e,Qi)}class Zi{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>Rr(this),()=>Or(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function Gi(e){return new Zi(e)}class el{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Pi(Q(this._object),this._key)}}class tl{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function nl(e,t,n){return ce(e)?e:W(e)?new tl(e):ee(e)&&arguments.length>1?rl(e,t,n):ae(e)}function rl(e,t,n){const r=e[t];return ce(r)?r:new el(e,t,n)}class sl{constructor(t,n,r,s){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new Er(t,()=>{this._dirty||(this._dirty=!0,Or(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!s,this.__v_isReadonly=r}get value(){const t=Q(this);return Rr(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function ol(e,t,n=!1){let r,s;const o=W(e);return o?(r=e,s=Oe):(r=e.get,s=e.set),new sl(r,s,o||!s,n)}function Je(e,t,n,r){let s;try{s=r?e(...r):e()}catch(o){Yt(o,t,n)}return s}function xe(e,t,n,r){if(W(e)){const o=Je(e,t,n,r);return o&&qs(o)&&o.catch(i=>{Yt(i,t,n)}),o}const s=[];for(let o=0;o>>1,s=he[r],o=Ut(s);oLe&&he.splice(t,1)}function al(e){U(e)?bt.push(...e):(!je||!je.includes(e,e.allowRecurse?rt+1:rt))&&bt.push(e),ho()}function ns(e,t=kt?Le+1:0){for(;tUt(n)-Ut(r)),rt=0;rte.id==null?1/0:e.id,ul=(e,t)=>{const n=Ut(e)-Ut(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function po(e){or=!1,kt=!0,he.sort(ul);const t=Oe;try{for(Le=0;Lene(w)?w.trim():w)),h&&(s=n.map(er))}let l,c=r[l=dn(t)]||r[l=dn(Ne(t))];!c&&o&&(c=r[l=dn(ft(t))]),c&&xe(c,e,6,s);const a=r[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,xe(a,e,6,s)}}function go(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let i={},l=!1;if(!W(e)){const c=a=>{const f=go(a,t,!0);f&&(l=!0,ue(i,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(ee(e)&&r.set(e,null),null):(U(o)?o.forEach(c=>i[c]=null):ue(i,o),ee(e)&&r.set(e,i),i)}function Ln(e,t){return!e||!zt(t)?!1:(t=t.slice(2).replace(/Once$/,""),X(e,t[0].toLowerCase()+t.slice(1))||X(e,ft(t))||X(e,t))}let de=null,Nn=null;function vn(e){const t=de;return de=e,Nn=e&&e.type.__scopeId||null,t}function Na(e){Nn=e}function Ha(){Nn=null}function dl(e,t=de,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&gs(-1);const o=vn(t);let i;try{i=e(...s)}finally{vn(o),r._d&&gs(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Wn(e){const{type:t,vnode:n,proxy:r,withProxy:s,props:o,propsOptions:[i],slots:l,attrs:c,emit:a,render:f,renderCache:h,data:m,setupState:w,ctx:E,inheritAttrs:T}=e;let L,B;const k=vn(e);try{if(n.shapeFlag&4){const p=s||r;L=Ae(f.call(p,p,h,o,w,m,E)),B=c}else{const p=t;L=Ae(p.length>1?p(o,{attrs:c,slots:l,emit:a}):p(o,null)),B=t.props?c:hl(c)}}catch(p){jt.length=0,Yt(p,e,1),L=re(ve)}let y=L;if(B&&T!==!1){const p=Object.keys(B),{shapeFlag:F}=y;p.length&&F&7&&(i&&p.some(yr)&&(B=pl(B,i)),y=Ze(y,B))}return n.dirs&&(y=Ze(y),y.dirs=y.dirs?y.dirs.concat(n.dirs):n.dirs),n.transition&&(y.transition=n.transition),L=y,vn(k),L}const hl=e=>{let t;for(const n in e)(n==="class"||n==="style"||zt(n))&&((t||(t={}))[n]=e[n]);return t},pl=(e,t)=>{const n={};for(const r in e)(!yr(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function gl(e,t,n){const{props:r,children:s,component:o}=e,{props:i,children:l,patchFlag:c}=t,a=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?rs(r,i,a):!!i;if(c&8){const f=t.dynamicProps;for(let h=0;he.__isSuspense;function mo(e,t){t&&t.pendingBranch?U(e)?t.effects.push(...e):t.effects.push(e):al(e)}function Ir(e,t){return Hn(e,null,t)}function $a(e,t){return Hn(e,null,{flush:"post"})}const rn={};function Xe(e,t,n){return Hn(e,t,n)}function Hn(e,t,{immediate:n,deep:r,flush:s,onTrack:o,onTrigger:i}=te){var l;const c=Qs()===((l=le)==null?void 0:l.scope)?le:null;let a,f=!1,h=!1;if(ce(e)?(a=()=>e.value,f=_n(e)):_t(e)?(a=()=>e,r=!0):U(e)?(h=!0,f=e.some(p=>_t(p)||_n(p)),a=()=>e.map(p=>{if(ce(p))return p.value;if(_t(p))return it(p);if(W(p))return Je(p,c,2)})):W(e)?t?a=()=>Je(e,c,2):a=()=>{if(!(c&&c.isUnmounted))return m&&m(),xe(e,c,3,[w])}:a=Oe,t&&r){const p=a;a=()=>it(p())}let m,w=p=>{m=k.onStop=()=>{Je(p,c,4)}},E;if(Tt)if(w=Oe,t?n&&xe(t,c,3,[a(),h?[]:void 0,w]):a(),s==="sync"){const p=hc();E=p.__watcherHandles||(p.__watcherHandles=[])}else return Oe;let T=h?new Array(e.length).fill(rn):rn;const L=()=>{if(k.active)if(t){const p=k.run();(r||f||(h?p.some((F,K)=>ut(F,T[K])):ut(p,T)))&&(m&&m(),xe(t,c,3,[p,T===rn?void 0:h&&T[0]===rn?[]:T,w]),T=p)}else k.run()};L.allowRecurse=!!t;let B;s==="sync"?B=L:s==="post"?B=()=>ge(L,c&&c.suspense):(L.pre=!0,c&&(L.id=c.uid),B=()=>In(L));const k=new Er(a,B);t?n?L():T=k.run():s==="post"?ge(k.run.bind(k),c&&c.suspense):k.run();const y=()=>{k.stop(),c&&c.scope&&_r(c.scope.effects,k)};return E&&E.push(y),y}function _l(e,t,n){const r=this.proxy,s=ne(e)?e.includes(".")?yo(r,e):()=>r[e]:e.bind(r,r);let o;W(t)?o=t:(o=t.handler,n=t);const i=le;xt(this);const l=Hn(s,o.bind(r),n);return i?xt(i):ct(),l}function yo(e,t){const n=t.split(".");return()=>{let r=e;for(let s=0;s{it(n,t)});else if(Ys(e))for(const n in e)it(e[n],t);return e}function ja(e,t){const n=de;if(n===null)return e;const r=kn(n)||n.proxy,s=e.dirs||(e.dirs=[]);for(let o=0;o{e.isMounted=!0}),Co(()=>{e.isUnmounting=!0}),e}const we=[Function,Array],_o={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:we,onEnter:we,onAfterEnter:we,onEnterCancelled:we,onBeforeLeave:we,onLeave:we,onAfterLeave:we,onLeaveCancelled:we,onBeforeAppear:we,onAppear:we,onAfterAppear:we,onAppearCancelled:we},vl={name:"BaseTransition",props:_o,setup(e,{slots:t}){const n=Bn(),r=bl();let s;return()=>{const o=t.default&&vo(t.default(),!0);if(!o||!o.length)return;let i=o[0];if(o.length>1){for(const T of o)if(T.type!==ve){i=T;break}}const l=Q(e),{mode:c}=l;if(r.isLeaving)return Vn(i);const a=ss(i);if(!a)return Vn(i);const f=ir(a,l,r,n);lr(a,f);const h=n.subTree,m=h&&ss(h);let w=!1;const{getTransitionKey:E}=a.type;if(E){const T=E();s===void 0?s=T:T!==s&&(s=T,w=!0)}if(m&&m.type!==ve&&(!st(a,m)||w)){const T=ir(m,l,r,n);if(lr(m,T),c==="out-in")return r.isLeaving=!0,T.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&n.update()},Vn(i);c==="in-out"&&a.type!==ve&&(T.delayLeave=(L,B,k)=>{const y=bo(r,m);y[String(m.key)]=m,L[qe]=()=>{B(),L[qe]=void 0,delete f.delayedLeave},f.delayedLeave=k})}return i}}},wl=vl;function bo(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function ir(e,t,n,r){const{appear:s,mode:o,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:h,onLeave:m,onAfterLeave:w,onLeaveCancelled:E,onBeforeAppear:T,onAppear:L,onAfterAppear:B,onAppearCancelled:k}=t,y=String(e.key),p=bo(n,e),F=(v,M)=>{v&&xe(v,r,9,M)},K=(v,M)=>{const R=M[1];F(v,M),U(v)?v.every(z=>z.length<=1)&&R():v.length<=1&&R()},N={mode:o,persisted:i,beforeEnter(v){let M=l;if(!n.isMounted)if(s)M=T||l;else return;v[qe]&&v[qe](!0);const R=p[y];R&&st(e,R)&&R.el[qe]&&R.el[qe](),F(M,[v])},enter(v){let M=c,R=a,z=f;if(!n.isMounted)if(s)M=L||c,R=B||a,z=k||f;else return;let O=!1;const q=v[sn]=oe=>{O||(O=!0,oe?F(z,[v]):F(R,[v]),N.delayedLeave&&N.delayedLeave(),v[sn]=void 0)};M?K(M,[v,q]):q()},leave(v,M){const R=String(e.key);if(v[sn]&&v[sn](!0),n.isUnmounting)return M();F(h,[v]);let z=!1;const O=v[qe]=q=>{z||(z=!0,M(),q?F(E,[v]):F(w,[v]),v[qe]=void 0,p[R]===e&&delete p[R])};p[R]=e,m?K(m,[v,O]):O()},clone(v){return ir(v,t,n,r)}};return N}function Vn(e){if(Jt(e))return e=Ze(e),e.children=null,e}function ss(e){return Jt(e)?e.children?e.children[0]:void 0:e}function lr(e,t){e.shapeFlag&6&&e.component?lr(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function vo(e,t=!1,n){let r=[],s=0;for(let o=0;o1)for(let o=0;oue({name:e.name},t,{setup:e}))():e}const vt=e=>!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function Da(e){W(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:s=200,timeout:o,suspensible:i=!0,onError:l}=e;let c=null,a,f=0;const h=()=>(f++,c=null,m()),m=()=>{let w;return c||(w=c=t().catch(E=>{if(E=E instanceof Error?E:new Error(String(E)),l)return new Promise((T,L)=>{l(E,()=>T(h()),()=>L(E),f+1)});throw E}).then(E=>w!==c&&c?c:(E&&(E.__esModule||E[Symbol.toStringTag]==="Module")&&(E=E.default),a=E,E)))};return Lr({name:"AsyncComponentWrapper",__asyncLoader:m,get __asyncResolved(){return a},setup(){const w=le;if(a)return()=>qn(a,w);const E=k=>{c=null,Yt(k,w,13,!r)};if(i&&w.suspense||Tt)return m().then(k=>()=>qn(k,w)).catch(k=>(E(k),()=>r?re(r,{error:k}):null));const T=ae(!1),L=ae(),B=ae(!!s);return s&&setTimeout(()=>{B.value=!1},s),o!=null&&setTimeout(()=>{if(!T.value&&!L.value){const k=new Error(`Async component timed out after ${o}ms.`);E(k),L.value=k}},o),m().then(()=>{T.value=!0,w.parent&&Jt(w.parent.vnode)&&In(w.parent.update)}).catch(k=>{E(k),L.value=k}),()=>{if(T.value&&a)return qn(a,w);if(L.value&&r)return re(r,{error:L.value});if(n&&!B.value)return re(n)}}})}function qn(e,t){const{ref:n,props:r,children:s,ce:o}=t.vnode,i=re(e,r,s);return i.ref=n,i.ce=o,delete t.vnode.ce,i}const Jt=e=>e.type.__isKeepAlive;function Cl(e,t){wo(e,"a",t)}function El(e,t){wo(e,"da",t)}function wo(e,t,n=le){const r=e.__wdc||(e.__wdc=()=>{let s=n;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if($n(t,r,n),n){let s=n.parent;for(;s&&s.parent;)Jt(s.parent.vnode)&&xl(r,t,n,s),s=s.parent}}function xl(e,t,n,r){const s=$n(t,e,r,!0);jn(()=>{_r(r[t],s)},n)}function $n(e,t,n=le,r=!1){if(n){const s=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;At(),xt(n);const l=xe(t,n,e,i);return ct(),St(),l});return r?s.unshift(o):s.push(o),o}}const ke=e=>(t,n=le)=>(!Tt||e==="sp")&&$n(e,(...r)=>t(...r),n),Tl=ke("bm"),Rt=ke("m"),Al=ke("bu"),Sl=ke("u"),Co=ke("bum"),jn=ke("um"),Rl=ke("sp"),Ol=ke("rtg"),Pl=ke("rtc");function Ml(e,t=le){$n("ec",e,t)}const Nr="components";function Ba(e,t){return xo(Nr,e,!0,t)||e}const Eo=Symbol.for("v-ndc");function ka(e){return ne(e)?xo(Nr,e,!1)||e:e||Eo}function xo(e,t,n=!0,r=!1){const s=de||le;if(s){const o=s.type;if(e===Nr){const l=uc(o,!1);if(l&&(l===t||l===Ne(t)||l===Rn(Ne(t))))return o}const i=os(s[e]||o[e],t)||os(s.appContext[e],t);return!i&&r?o:i}}function os(e,t){return e&&(e[t]||e[Ne(t)]||e[Rn(Ne(t))])}function Ua(e,t,n,r){let s;const o=n&&n[r];if(U(e)||ne(e)){s=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,o&&o[l]));else{const i=Object.keys(e);s=new Array(i.length);for(let l=0,c=i.length;lxn(t)?!(t.type===ve||t.type===me&&!To(t.children)):!0)?e:null}function Wa(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:dn(r)]=e[r];return n}const cr=e=>e?Uo(e)?kn(e)||e.proxy:cr(e.parent):null,Nt=ue(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>cr(e.parent),$root:e=>cr(e.root),$emit:e=>e.emit,$options:e=>Hr(e),$forceUpdate:e=>e.f||(e.f=()=>In(e.update)),$nextTick:e=>e.n||(e.n=Fn.bind(e.proxy)),$watch:e=>_l.bind(e)}),zn=(e,t)=>e!==te&&!e.__isScriptSetup&&X(e,t),Fl={get({_:e},t){const{ctx:n,setupState:r,data:s,props:o,accessCache:i,type:l,appContext:c}=e;let a;if(t[0]!=="$"){const w=i[t];if(w!==void 0)switch(w){case 1:return r[t];case 2:return s[t];case 4:return n[t];case 3:return o[t]}else{if(zn(r,t))return i[t]=1,r[t];if(s!==te&&X(s,t))return i[t]=2,s[t];if((a=e.propsOptions[0])&&X(a,t))return i[t]=3,o[t];if(n!==te&&X(n,t))return i[t]=4,n[t];ar&&(i[t]=0)}}const f=Nt[t];let h,m;if(f)return t==="$attrs"&&ye(e,"get",t),f(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==te&&X(n,t))return i[t]=4,n[t];if(m=c.config.globalProperties,X(m,t))return m[t]},set({_:e},t,n){const{data:r,setupState:s,ctx:o}=e;return zn(s,t)?(s[t]=n,!0):r!==te&&X(r,t)?(r[t]=n,!0):X(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:s,propsOptions:o}},i){let l;return!!n[i]||e!==te&&X(e,i)||zn(t,i)||(l=o[0])&&X(l,i)||X(r,i)||X(Nt,i)||X(s.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:X(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Va(){return Il().slots}function Il(){const e=Bn();return e.setupContext||(e.setupContext=Wo(e))}function is(e){return U(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let ar=!0;function Ll(e){const t=Hr(e),n=e.proxy,r=e.ctx;ar=!1,t.beforeCreate&&ls(t.beforeCreate,e,"bc");const{data:s,computed:o,methods:i,watch:l,provide:c,inject:a,created:f,beforeMount:h,mounted:m,beforeUpdate:w,updated:E,activated:T,deactivated:L,beforeDestroy:B,beforeUnmount:k,destroyed:y,unmounted:p,render:F,renderTracked:K,renderTriggered:N,errorCaptured:v,serverPrefetch:M,expose:R,inheritAttrs:z,components:O,directives:q,filters:oe}=t;if(a&&Nl(a,r,null),i)for(const Y in i){const D=i[Y];W(D)&&(r[Y]=D.bind(n))}if(s){const Y=s.call(n,n);ee(Y)&&(e.data=Pn(Y))}if(ar=!0,o)for(const Y in o){const D=o[Y],He=W(D)?D.bind(n,n):W(D.get)?D.get.bind(n,n):Oe,Xt=!W(D)&&W(D.set)?D.set.bind(n):Oe,Ge=ie({get:He,set:Xt});Object.defineProperty(r,Y,{enumerable:!0,configurable:!0,get:()=>Ge.value,set:Me=>Ge.value=Me})}if(l)for(const Y in l)Ao(l[Y],r,n,Y);if(c){const Y=W(c)?c.call(n):c;Reflect.ownKeys(Y).forEach(D=>{kl(D,Y[D])})}f&&ls(f,e,"c");function H(Y,D){U(D)?D.forEach(He=>Y(He.bind(n))):D&&Y(D.bind(n))}if(H(Tl,h),H(Rt,m),H(Al,w),H(Sl,E),H(Cl,T),H(El,L),H(Ml,v),H(Pl,K),H(Ol,N),H(Co,k),H(jn,p),H(Rl,M),U(R))if(R.length){const Y=e.exposed||(e.exposed={});R.forEach(D=>{Object.defineProperty(Y,D,{get:()=>n[D],set:He=>n[D]=He})})}else e.exposed||(e.exposed={});F&&e.render===Oe&&(e.render=F),z!=null&&(e.inheritAttrs=z),O&&(e.components=O),q&&(e.directives=q)}function Nl(e,t,n=Oe){U(e)&&(e=ur(e));for(const r in e){const s=e[r];let o;ee(s)?"default"in s?o=wt(s.from||r,s.default,!0):o=wt(s.from||r):o=wt(s),ce(o)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:i=>o.value=i}):t[r]=o}}function ls(e,t,n){xe(U(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function Ao(e,t,n,r){const s=r.includes(".")?yo(n,r):()=>n[r];if(ne(e)){const o=t[e];W(o)&&Xe(s,o)}else if(W(e))Xe(s,e.bind(n));else if(ee(e))if(U(e))e.forEach(o=>Ao(o,t,n,r));else{const o=W(e.handler)?e.handler.bind(n):t[e.handler];W(o)&&Xe(s,o,e)}}function Hr(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:s,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,l=o.get(t);let c;return l?c=l:!s.length&&!n&&!r?c=t:(c={},s.length&&s.forEach(a=>wn(c,a,i,!0)),wn(c,t,i)),ee(t)&&o.set(t,c),c}function wn(e,t,n,r=!1){const{mixins:s,extends:o}=t;o&&wn(e,o,n,!0),s&&s.forEach(i=>wn(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=Hl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Hl={data:cs,props:as,emits:as,methods:Ft,computed:Ft,beforeCreate:pe,created:pe,beforeMount:pe,mounted:pe,beforeUpdate:pe,updated:pe,beforeDestroy:pe,beforeUnmount:pe,destroyed:pe,unmounted:pe,activated:pe,deactivated:pe,errorCaptured:pe,serverPrefetch:pe,components:Ft,directives:Ft,watch:jl,provide:cs,inject:$l};function cs(e,t){return t?e?function(){return ue(W(e)?e.call(this,this):e,W(t)?t.call(this,this):t)}:t:e}function $l(e,t){return Ft(ur(e),ur(t))}function ur(e){if(U(e)){const t={};for(let n=0;n1)return n&&W(t)?t.call(r&&r.proxy):t}}function Ul(e,t,n,r=!1){const s={},o={};mn(o,Dn,1),e.propsDefaults=Object.create(null),Ro(e,t,s,o);for(const i in e.propsOptions[0])i in s||(s[i]=void 0);n?e.props=r?s:Ji(s):e.type.props?e.props=s:e.props=o,e.attrs=o}function Kl(e,t,n,r){const{props:s,attrs:o,vnode:{patchFlag:i}}=e,l=Q(s),[c]=e.propsOptions;let a=!1;if((r||i>0)&&!(i&16)){if(i&8){const f=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[m,w]=Oo(h,t,!0);ue(i,m),w&&l.push(...w)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!o&&!c)return ee(e)&&r.set(e,mt),mt;if(U(o))for(let f=0;f-1,w[1]=T<0||E-1||X(w,"default"))&&l.push(h)}}}const a=[i,l];return ee(e)&&r.set(e,a),a}function us(e){return e[0]!=="$"}function fs(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function ds(e,t){return fs(e)===fs(t)}function hs(e,t){return U(t)?t.findIndex(n=>ds(n,e)):W(t)&&ds(t,e)?0:-1}const Po=e=>e[0]==="_"||e==="$stable",$r=e=>U(e)?e.map(Ae):[Ae(e)],Wl=(e,t,n)=>{if(t._n)return t;const r=dl((...s)=>$r(t(...s)),n);return r._c=!1,r},Mo=(e,t,n)=>{const r=e._ctx;for(const s in e){if(Po(s))continue;const o=e[s];if(W(o))t[s]=Wl(s,o,r);else if(o!=null){const i=$r(o);t[s]=()=>i}}},Fo=(e,t)=>{const n=$r(t);e.slots.default=()=>n},Vl=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=Q(t),mn(t,"_",n)):Mo(t,e.slots={})}else e.slots={},t&&Fo(e,t);mn(e.slots,Dn,1)},ql=(e,t,n)=>{const{vnode:r,slots:s}=e;let o=!0,i=te;if(r.shapeFlag&32){const l=t._;l?n&&l===1?o=!1:(ue(s,t),!n&&l===1&&delete s._):(o=!t.$stable,Mo(t,s)),i=t}else t&&(Fo(e,t),i={default:1});if(o)for(const l in s)!Po(l)&&i[l]==null&&delete s[l]};function En(e,t,n,r,s=!1){if(U(e)){e.forEach((m,w)=>En(m,t&&(U(t)?t[w]:t),n,r,s));return}if(vt(r)&&!s)return;const o=r.shapeFlag&4?kn(r.component)||r.component.proxy:r.el,i=s?null:o,{i:l,r:c}=e,a=t&&t.r,f=l.refs===te?l.refs={}:l.refs,h=l.setupState;if(a!=null&&a!==c&&(ne(a)?(f[a]=null,X(h,a)&&(h[a]=null)):ce(a)&&(a.value=null)),W(c))Je(c,l,12,[i,f]);else{const m=ne(c),w=ce(c);if(m||w){const E=()=>{if(e.f){const T=m?X(h,c)?h[c]:f[c]:c.value;s?U(T)&&_r(T,o):U(T)?T.includes(o)||T.push(o):m?(f[c]=[o],X(h,c)&&(h[c]=f[c])):(c.value=[o],e.k&&(f[e.k]=c.value))}else m?(f[c]=i,X(h,c)&&(h[c]=i)):w&&(c.value=i,e.k&&(f[e.k]=i))};i?(E.id=-1,ge(E,n)):E()}}}let Ke=!1;const on=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",ln=e=>e.nodeType===8;function zl(e){const{mt:t,p:n,o:{patchProp:r,createText:s,nextSibling:o,parentNode:i,remove:l,insert:c,createComment:a}}=e,f=(y,p)=>{if(!p.hasChildNodes()){n(null,y,p),bn(),p._vnode=y;return}Ke=!1,h(p.firstChild,y,null,null,null),bn(),p._vnode=y,Ke&&console.error("Hydration completed but contains mismatches.")},h=(y,p,F,K,N,v=!1)=>{const M=ln(y)&&y.data==="[",R=()=>T(y,p,F,K,N,M),{type:z,ref:O,shapeFlag:q,patchFlag:oe}=p;let fe=y.nodeType;p.el=y,oe===-2&&(v=!1,p.dynamicChildren=null);let H=null;switch(z){case Et:fe!==3?p.children===""?(c(p.el=s(""),i(y),y),H=y):H=R():(y.data!==p.children&&(Ke=!0,y.data=p.children),H=o(y));break;case ve:if(fe!==8||M)if(y.tagName.toLowerCase()==="template"){const Y=p.el.content.firstChild;B(Y,y,F),p.el=y=Y,H=o(y)}else H=R();else H=o(y);break;case $t:if(M&&(y=o(y),fe=y.nodeType),fe===1||fe===3){H=y;const Y=!p.children.length;for(let D=0;D{v=v||!!p.dynamicChildren;const{type:M,props:R,patchFlag:z,shapeFlag:O,dirs:q,transition:oe}=p,fe=M==="input"&&q||M==="option";if(fe||z!==-1){if(q&&Ie(p,null,F,"created"),R)if(fe||!v||z&48)for(const D in R)(fe&&D.endsWith("value")||zt(D)&&!It(D))&&r(y,D,null,R[D],!1,void 0,F);else R.onClick&&r(y,"onClick",null,R.onClick,!1,void 0,F);let H;(H=R&&R.onVnodeBeforeMount)&&Ce(H,F,p);let Y=!1;if(k(y)){Y=Lo(K,oe)&&F&&F.vnode.props&&F.vnode.props.appear;const D=y.content.firstChild;Y&&oe.beforeEnter(D),B(D,y,F),p.el=y=D}if(q&&Ie(p,null,F,"beforeMount"),((H=R&&R.onVnodeMounted)||q||Y)&&mo(()=>{H&&Ce(H,F,p),Y&&oe.enter(y),q&&Ie(p,null,F,"mounted")},K),O&16&&!(R&&(R.innerHTML||R.textContent))){let D=w(y.firstChild,p,y,F,K,N,v);for(;D;){Ke=!0;const He=D;D=D.nextSibling,l(He)}}else O&8&&y.textContent!==p.children&&(Ke=!0,y.textContent=p.children)}return y.nextSibling},w=(y,p,F,K,N,v,M)=>{M=M||!!p.dynamicChildren;const R=p.children,z=R.length;for(let O=0;O{const{slotScopeIds:M}=p;M&&(N=N?N.concat(M):M);const R=i(y),z=w(o(y),p,R,F,K,N,v);return z&&ln(z)&&z.data==="]"?o(p.anchor=z):(Ke=!0,c(p.anchor=a("]"),R,z),z)},T=(y,p,F,K,N,v)=>{if(Ke=!0,p.el=null,v){const z=L(y);for(;;){const O=o(y);if(O&&O!==z)l(O);else break}}const M=o(y),R=i(y);return l(y),n(null,p,R,M,F,K,on(R),N),M},L=(y,p="[",F="]")=>{let K=0;for(;y;)if(y=o(y),y&&ln(y)&&(y.data===p&&K++,y.data===F)){if(K===0)return o(y);K--}return y},B=(y,p,F)=>{const K=p.parentNode;K&&K.replaceChild(y,p);let N=F;for(;N;)N.vnode.el===p&&(N.vnode.el=y,N.subTree.el=y),N=N.parent},k=y=>y.nodeType===1&&y.tagName.toLowerCase()==="template";return[f,h]}const ge=mo;function Yl(e){return Io(e)}function Jl(e){return Io(e,zl)}function Io(e,t){const n=tr();n.__VUE__=!0;const{insert:r,remove:s,patchProp:o,createElement:i,createText:l,createComment:c,setText:a,setElementText:f,parentNode:h,nextSibling:m,setScopeId:w=Oe,insertStaticContent:E}=e,T=(u,d,g,_=null,b=null,A=null,P=!1,x=null,S=!!d.dynamicChildren)=>{if(u===d)return;u&&!st(u,d)&&(_=Qt(u),Me(u,b,A,!0),u=null),d.patchFlag===-2&&(S=!1,d.dynamicChildren=null);const{type:C,ref:$,shapeFlag:I}=d;switch(C){case Et:L(u,d,g,_);break;case ve:B(u,d,g,_);break;case $t:u==null&&k(d,g,_,P);break;case me:O(u,d,g,_,b,A,P,x,S);break;default:I&1?F(u,d,g,_,b,A,P,x,S):I&6?q(u,d,g,_,b,A,P,x,S):(I&64||I&128)&&C.process(u,d,g,_,b,A,P,x,S,dt)}$!=null&&b&&En($,u&&u.ref,A,d||u,!d)},L=(u,d,g,_)=>{if(u==null)r(d.el=l(d.children),g,_);else{const b=d.el=u.el;d.children!==u.children&&a(b,d.children)}},B=(u,d,g,_)=>{u==null?r(d.el=c(d.children||""),g,_):d.el=u.el},k=(u,d,g,_)=>{[u.el,u.anchor]=E(u.children,d,g,_,u.el,u.anchor)},y=({el:u,anchor:d},g,_)=>{let b;for(;u&&u!==d;)b=m(u),r(u,g,_),u=b;r(d,g,_)},p=({el:u,anchor:d})=>{let g;for(;u&&u!==d;)g=m(u),s(u),u=g;s(d)},F=(u,d,g,_,b,A,P,x,S)=>{P=P||d.type==="svg",u==null?K(d,g,_,b,A,P,x,S):M(u,d,b,A,P,x,S)},K=(u,d,g,_,b,A,P,x)=>{let S,C;const{type:$,props:I,shapeFlag:j,transition:V,dirs:J}=u;if(S=u.el=i(u.type,A,I&&I.is,I),j&8?f(S,u.children):j&16&&v(u.children,S,null,_,b,A&&$!=="foreignObject",P,x),J&&Ie(u,null,_,"created"),N(S,u,u.scopeId,P,_),I){for(const Z in I)Z!=="value"&&!It(Z)&&o(S,Z,null,I[Z],A,u.children,_,b,$e);"value"in I&&o(S,"value",null,I.value),(C=I.onVnodeBeforeMount)&&Ce(C,_,u)}J&&Ie(u,null,_,"beforeMount");const G=Lo(b,V);G&&V.beforeEnter(S),r(S,d,g),((C=I&&I.onVnodeMounted)||G||J)&&ge(()=>{C&&Ce(C,_,u),G&&V.enter(S),J&&Ie(u,null,_,"mounted")},b)},N=(u,d,g,_,b)=>{if(g&&w(u,g),_)for(let A=0;A<_.length;A++)w(u,_[A]);if(b){let A=b.subTree;if(d===A){const P=b.vnode;N(u,P,P.scopeId,P.slotScopeIds,b.parent)}}},v=(u,d,g,_,b,A,P,x,S=0)=>{for(let C=S;C{const x=d.el=u.el;let{patchFlag:S,dynamicChildren:C,dirs:$}=d;S|=u.patchFlag&16;const I=u.props||te,j=d.props||te;let V;g&&et(g,!1),(V=j.onVnodeBeforeUpdate)&&Ce(V,g,d,u),$&&Ie(d,u,g,"beforeUpdate"),g&&et(g,!0);const J=b&&d.type!=="foreignObject";if(C?R(u.dynamicChildren,C,x,g,_,J,A):P||D(u,d,x,null,g,_,J,A,!1),S>0){if(S&16)z(x,d,I,j,g,_,b);else if(S&2&&I.class!==j.class&&o(x,"class",null,j.class,b),S&4&&o(x,"style",I.style,j.style,b),S&8){const G=d.dynamicProps;for(let Z=0;Z{V&&Ce(V,g,d,u),$&&Ie(d,u,g,"updated")},_)},R=(u,d,g,_,b,A,P)=>{for(let x=0;x{if(g!==_){if(g!==te)for(const x in g)!It(x)&&!(x in _)&&o(u,x,g[x],null,P,d.children,b,A,$e);for(const x in _){if(It(x))continue;const S=_[x],C=g[x];S!==C&&x!=="value"&&o(u,x,C,S,P,d.children,b,A,$e)}"value"in _&&o(u,"value",g.value,_.value)}},O=(u,d,g,_,b,A,P,x,S)=>{const C=d.el=u?u.el:l(""),$=d.anchor=u?u.anchor:l("");let{patchFlag:I,dynamicChildren:j,slotScopeIds:V}=d;V&&(x=x?x.concat(V):V),u==null?(r(C,g,_),r($,g,_),v(d.children,g,$,b,A,P,x,S)):I>0&&I&64&&j&&u.dynamicChildren?(R(u.dynamicChildren,j,g,b,A,P,x),(d.key!=null||b&&d===b.subTree)&&jr(u,d,!0)):D(u,d,g,$,b,A,P,x,S)},q=(u,d,g,_,b,A,P,x,S)=>{d.slotScopeIds=x,u==null?d.shapeFlag&512?b.ctx.activate(d,g,_,P,S):oe(d,g,_,b,A,P,S):fe(u,d,S)},oe=(u,d,g,_,b,A,P)=>{const x=u.component=ic(u,_,b);if(Jt(u)&&(x.ctx.renderer=dt),lc(x),x.asyncDep){if(b&&b.registerDep(x,H),!u.el){const S=x.subTree=re(ve);B(null,S,d,g)}return}H(x,u,d,g,b,A,P)},fe=(u,d,g)=>{const _=d.component=u.component;if(gl(u,d,g))if(_.asyncDep&&!_.asyncResolved){Y(_,d,g);return}else _.next=d,cl(_.update),_.update();else d.el=u.el,_.vnode=d},H=(u,d,g,_,b,A,P)=>{const x=()=>{if(u.isMounted){let{next:$,bu:I,u:j,parent:V,vnode:J}=u,G=$,Z;et(u,!1),$?($.el=J.el,Y(u,$,P)):$=J,I&&hn(I),(Z=$.props&&$.props.onVnodeBeforeUpdate)&&Ce(Z,V,$,J),et(u,!0);const se=Wn(u),Te=u.subTree;u.subTree=se,T(Te,se,h(Te.el),Qt(Te),u,b,A),$.el=se.el,G===null&&ml(u,se.el),j&&ge(j,b),(Z=$.props&&$.props.onVnodeUpdated)&&ge(()=>Ce(Z,V,$,J),b)}else{let $;const{el:I,props:j}=d,{bm:V,m:J,parent:G}=u,Z=vt(d);if(et(u,!1),V&&hn(V),!Z&&($=j&&j.onVnodeBeforeMount)&&Ce($,G,d),et(u,!0),I&&Kn){const se=()=>{u.subTree=Wn(u),Kn(I,u.subTree,u,b,null)};Z?d.type.__asyncLoader().then(()=>!u.isUnmounted&&se()):se()}else{const se=u.subTree=Wn(u);T(null,se,g,_,u,b,A),d.el=se.el}if(J&&ge(J,b),!Z&&($=j&&j.onVnodeMounted)){const se=d;ge(()=>Ce($,G,se),b)}(d.shapeFlag&256||G&&vt(G.vnode)&&G.vnode.shapeFlag&256)&&u.a&&ge(u.a,b),u.isMounted=!0,d=g=_=null}},S=u.effect=new Er(x,()=>In(C),u.scope),C=u.update=()=>S.run();C.id=u.uid,et(u,!0),C()},Y=(u,d,g)=>{d.component=u;const _=u.vnode.props;u.vnode=d,u.next=null,Kl(u,d.props,_,g),ql(u,d.children,g),At(),ns(),St()},D=(u,d,g,_,b,A,P,x,S=!1)=>{const C=u&&u.children,$=u?u.shapeFlag:0,I=d.children,{patchFlag:j,shapeFlag:V}=d;if(j>0){if(j&128){Xt(C,I,g,_,b,A,P,x,S);return}else if(j&256){He(C,I,g,_,b,A,P,x,S);return}}V&8?($&16&&$e(C,b,A),I!==C&&f(g,I)):$&16?V&16?Xt(C,I,g,_,b,A,P,x,S):$e(C,b,A,!0):($&8&&f(g,""),V&16&&v(I,g,_,b,A,P,x,S))},He=(u,d,g,_,b,A,P,x,S)=>{u=u||mt,d=d||mt;const C=u.length,$=d.length,I=Math.min(C,$);let j;for(j=0;j$?$e(u,b,A,!0,!1,I):v(d,g,_,b,A,P,x,S,I)},Xt=(u,d,g,_,b,A,P,x,S)=>{let C=0;const $=d.length;let I=u.length-1,j=$-1;for(;C<=I&&C<=j;){const V=u[C],J=d[C]=S?ze(d[C]):Ae(d[C]);if(st(V,J))T(V,J,g,null,b,A,P,x,S);else break;C++}for(;C<=I&&C<=j;){const V=u[I],J=d[j]=S?ze(d[j]):Ae(d[j]);if(st(V,J))T(V,J,g,null,b,A,P,x,S);else break;I--,j--}if(C>I){if(C<=j){const V=j+1,J=V<$?d[V].el:_;for(;C<=j;)T(null,d[C]=S?ze(d[C]):Ae(d[C]),g,J,b,A,P,x,S),C++}}else if(C>j)for(;C<=I;)Me(u[C],b,A,!0),C++;else{const V=C,J=C,G=new Map;for(C=J;C<=j;C++){const _e=d[C]=S?ze(d[C]):Ae(d[C]);_e.key!=null&&G.set(_e.key,C)}let Z,se=0;const Te=j-J+1;let ht=!1,Vr=0;const Ot=new Array(Te);for(C=0;C=Te){Me(_e,b,A,!0);continue}let Fe;if(_e.key!=null)Fe=G.get(_e.key);else for(Z=J;Z<=j;Z++)if(Ot[Z-J]===0&&st(_e,d[Z])){Fe=Z;break}Fe===void 0?Me(_e,b,A,!0):(Ot[Fe-J]=C+1,Fe>=Vr?Vr=Fe:ht=!0,T(_e,d[Fe],g,null,b,A,P,x,S),se++)}const qr=ht?Xl(Ot):mt;for(Z=qr.length-1,C=Te-1;C>=0;C--){const _e=J+C,Fe=d[_e],zr=_e+1<$?d[_e+1].el:_;Ot[C]===0?T(null,Fe,g,zr,b,A,P,x,S):ht&&(Z<0||C!==qr[Z]?Ge(Fe,g,zr,2):Z--)}}},Ge=(u,d,g,_,b=null)=>{const{el:A,type:P,transition:x,children:S,shapeFlag:C}=u;if(C&6){Ge(u.component.subTree,d,g,_);return}if(C&128){u.suspense.move(d,g,_);return}if(C&64){P.move(u,d,g,dt);return}if(P===me){r(A,d,g);for(let I=0;Ix.enter(A),b);else{const{leave:I,delayLeave:j,afterLeave:V}=x,J=()=>r(A,d,g),G=()=>{I(A,()=>{J(),V&&V()})};j?j(A,J,G):G()}else r(A,d,g)},Me=(u,d,g,_=!1,b=!1)=>{const{type:A,props:P,ref:x,children:S,dynamicChildren:C,shapeFlag:$,patchFlag:I,dirs:j}=u;if(x!=null&&En(x,null,g,u,!0),$&256){d.ctx.deactivate(u);return}const V=$&1&&j,J=!vt(u);let G;if(J&&(G=P&&P.onVnodeBeforeUnmount)&&Ce(G,d,u),$&6)fi(u.component,g,_);else{if($&128){u.suspense.unmount(g,_);return}V&&Ie(u,null,d,"beforeUnmount"),$&64?u.type.remove(u,d,g,b,dt,_):C&&(A!==me||I>0&&I&64)?$e(C,d,g,!1,!0):(A===me&&I&384||!b&&$&16)&&$e(S,d,g),_&&Kr(u)}(J&&(G=P&&P.onVnodeUnmounted)||V)&&ge(()=>{G&&Ce(G,d,u),V&&Ie(u,null,d,"unmounted")},g)},Kr=u=>{const{type:d,el:g,anchor:_,transition:b}=u;if(d===me){ui(g,_);return}if(d===$t){p(u);return}const A=()=>{s(g),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(u.shapeFlag&1&&b&&!b.persisted){const{leave:P,delayLeave:x}=b,S=()=>P(g,A);x?x(u.el,A,S):S()}else A()},ui=(u,d)=>{let g;for(;u!==d;)g=m(u),s(u),u=g;s(d)},fi=(u,d,g)=>{const{bum:_,scope:b,update:A,subTree:P,um:x}=u;_&&hn(_),b.stop(),A&&(A.active=!1,Me(P,u,d,g)),x&&ge(x,d),ge(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},$e=(u,d,g,_=!1,b=!1,A=0)=>{for(let P=A;Pu.shapeFlag&6?Qt(u.component.subTree):u.shapeFlag&128?u.suspense.next():m(u.anchor||u.el),Wr=(u,d,g)=>{u==null?d._vnode&&Me(d._vnode,null,null,!0):T(d._vnode||null,u,d,null,null,null,g),ns(),bn(),d._vnode=u},dt={p:T,um:Me,m:Ge,r:Kr,mt:oe,mc:v,pc:D,pbc:R,n:Qt,o:e};let Un,Kn;return t&&([Un,Kn]=t(dt)),{render:Wr,hydrate:Un,createApp:Bl(Wr,Un)}}function et({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Lo(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function jr(e,t,n=!1){const r=e.children,s=t.children;if(U(r)&&U(s))for(let o=0;o>1,e[n[l]]0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}const Ql=e=>e.__isTeleport,Ht=e=>e&&(e.disabled||e.disabled===""),ps=e=>typeof SVGElement<"u"&&e instanceof SVGElement,dr=(e,t)=>{const n=e&&e.to;return ne(n)?t?t(n):null:n},Zl={__isTeleport:!0,process(e,t,n,r,s,o,i,l,c,a){const{mc:f,pc:h,pbc:m,o:{insert:w,querySelector:E,createText:T,createComment:L}}=a,B=Ht(t.props);let{shapeFlag:k,children:y,dynamicChildren:p}=t;if(e==null){const F=t.el=T(""),K=t.anchor=T("");w(F,n,r),w(K,n,r);const N=t.target=dr(t.props,E),v=t.targetAnchor=T("");N&&(w(v,N),i=i||ps(N));const M=(R,z)=>{k&16&&f(y,R,z,s,o,i,l,c)};B?M(n,K):N&&M(N,v)}else{t.el=e.el;const F=t.anchor=e.anchor,K=t.target=e.target,N=t.targetAnchor=e.targetAnchor,v=Ht(e.props),M=v?n:K,R=v?F:N;if(i=i||ps(K),p?(m(e.dynamicChildren,p,M,s,o,i,l),jr(e,t,!0)):c||h(e,t,M,R,s,o,i,l,!1),B)v?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):cn(t,n,F,a,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const z=t.target=dr(t.props,E);z&&cn(t,z,null,a,0)}else v&&cn(t,K,N,a,1)}No(t)},remove(e,t,n,r,{um:s,o:{remove:o}},i){const{shapeFlag:l,children:c,anchor:a,targetAnchor:f,target:h,props:m}=e;if(h&&o(f),i&&o(a),l&16){const w=i||!Ht(m);for(let E=0;E0?Re||mt:null,ec(),Kt>0&&Re&&Re.push(e),e}function za(e,t,n,r,s,o){return $o(Bo(e,t,n,r,s,o,!0))}function jo(e,t,n,r,s){return $o(re(e,t,n,r,s,!0))}function xn(e){return e?e.__v_isVNode===!0:!1}function st(e,t){return e.type===t.type&&e.key===t.key}const Dn="__vInternal",Do=({key:e})=>e??null,pn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ne(e)||ce(e)||W(e)?{i:de,r:e,k:t,f:!!n}:e:null);function Bo(e,t=null,n=null,r=0,s=null,o=e===me?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Do(t),ref:t&&pn(t),scopeId:Nn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:de};return l?(Dr(c,n),o&128&&e.normalize(c)):n&&(c.shapeFlag|=ne(n)?8:16),Kt>0&&!i&&Re&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&Re.push(c),c}const re=tc;function tc(e,t=null,n=null,r=0,s=null,o=!1){if((!e||e===Eo)&&(e=ve),xn(e)){const l=Ze(e,t,!0);return n&&Dr(l,n),Kt>0&&!o&&Re&&(l.shapeFlag&6?Re[Re.indexOf(e)]=l:Re.push(l)),l.patchFlag|=-2,l}if(fc(e)&&(e=e.__vccOpts),t){t=nc(t);let{class:l,style:c}=t;l&&!ne(l)&&(t.class=wr(l)),ee(c)&&(co(c)&&!U(c)&&(c=ue({},c)),t.style=vr(c))}const i=ne(e)?1:yl(e)?128:Ql(e)?64:ee(e)?4:W(e)?2:0;return Bo(e,t,n,r,s,i,o,!0)}function nc(e){return e?co(e)||Dn in e?ue({},e):e:null}function Ze(e,t,n=!1){const{props:r,ref:s,patchFlag:o,children:i}=e,l=t?rc(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Do(l),ref:t&&t.ref?n&&s?U(s)?s.concat(pn(t)):[s,pn(t)]:pn(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==me?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ze(e.ssContent),ssFallback:e.ssFallback&&Ze(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ko(e=" ",t=0){return re(Et,null,e,t)}function Ya(e,t){const n=re($t,null,e);return n.staticCount=t,n}function Ja(e="",t=!1){return t?(Ho(),jo(ve,null,e)):re(ve,null,e)}function Ae(e){return e==null||typeof e=="boolean"?re(ve):U(e)?re(me,null,e.slice()):typeof e=="object"?ze(e):re(Et,null,String(e))}function ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Ze(e)}function Dr(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(U(t))n=16;else if(typeof t=="object")if(r&65){const s=t.default;s&&(s._c&&(s._d=!1),Dr(e,s()),s._c&&(s._d=!0));return}else{n=32;const s=t._;!s&&!(Dn in t)?t._ctx=de:s===3&&de&&(de.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else W(t)?(t={default:t,_ctx:de},n=32):(t=String(t),r&64?(n=16,t=[ko(t)]):n=8);e.children=t,e.shapeFlag|=n}function rc(...e){const t={};for(let n=0;nle||de;let Br,pt,ms="__VUE_INSTANCE_SETTERS__";(pt=tr()[ms])||(pt=tr()[ms]=[]),pt.push(e=>le=e),Br=e=>{pt.length>1?pt.forEach(t=>t(e)):pt[0](e)};const xt=e=>{Br(e),e.scope.on()},ct=()=>{le&&le.scope.off(),Br(null)};function Uo(e){return e.vnode.shapeFlag&4}let Tt=!1;function lc(e,t=!1){Tt=t;const{props:n,children:r}=e.vnode,s=Uo(e);Ul(e,n,s,t),Vl(e,r);const o=s?cc(e,t):void 0;return Tt=!1,o}function cc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Lt(new Proxy(e.ctx,Fl));const{setup:r}=n;if(r){const s=e.setupContext=r.length>1?Wo(e):null;xt(e),At();const o=Je(r,e,0,[e.props,s]);if(St(),ct(),qs(o)){if(o.then(ct,ct),t)return o.then(i=>{ys(e,i,t)}).catch(i=>{Yt(i,e,0)});e.asyncDep=o}else ys(e,o,t)}else Ko(e,t)}function ys(e,t,n){W(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ee(t)&&(e.setupState=uo(t)),Ko(e,n)}let _s;function Ko(e,t,n){const r=e.type;if(!e.render){if(!t&&_s&&!r.render){const s=r.template||Hr(e).template;if(s){const{isCustomElement:o,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=r,a=ue(ue({isCustomElement:o,delimiters:l},i),c);r.render=_s(s,a)}}e.render=r.render||Oe}{xt(e),At();try{Ll(e)}finally{St(),ct()}}}function ac(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return ye(e,"get","$attrs"),t[n]}}))}function Wo(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return ac(e)},slots:e.slots,emit:e.emit,expose:t}}function kn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(uo(Lt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Nt)return Nt[n](e)},has(t,n){return n in t||n in Nt}}))}function uc(e,t=!0){return W(e)?e.displayName||e.name:e.name||t&&e.__name}function fc(e){return W(e)&&"__vccOpts"in e}const ie=(e,t)=>ol(e,t,Tt);function hr(e,t,n){const r=arguments.length;return r===2?ee(t)&&!U(t)?xn(t)?re(e,null,[t]):re(e,t):re(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&xn(n)&&(n=[n]),re(e,t,n))}const dc=Symbol.for("v-scx"),hc=()=>wt(dc),pc="3.3.7",gc="http://www.w3.org/2000/svg",ot=typeof document<"u"?document:null,bs=ot&&ot.createElement("template"),mc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t?ot.createElementNS(gc,e):ot.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>ot.createTextNode(e),createComment:e=>ot.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ot.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const i=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{bs.innerHTML=r?`${e}`:e;const l=bs.content;if(r){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},We="transition",Pt="animation",Wt=Symbol("_vtc"),Vo=(e,{slots:t})=>hr(wl,yc(e),t);Vo.displayName="Transition";const qo={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};Vo.props=ue({},_o,qo);const tt=(e,t=[])=>{U(e)?e.forEach(n=>n(...t)):e&&e(...t)},vs=e=>e?U(e)?e.some(t=>t.length>1):e.length>1:!1;function yc(e){const t={};for(const O in e)O in qo||(t[O]=e[O]);if(e.css===!1)return t;const{name:n="v",type:r,duration:s,enterFromClass:o=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=o,appearActiveClass:a=i,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:m=`${n}-leave-active`,leaveToClass:w=`${n}-leave-to`}=e,E=_c(s),T=E&&E[0],L=E&&E[1],{onBeforeEnter:B,onEnter:k,onEnterCancelled:y,onLeave:p,onLeaveCancelled:F,onBeforeAppear:K=B,onAppear:N=k,onAppearCancelled:v=y}=t,M=(O,q,oe)=>{nt(O,q?f:l),nt(O,q?a:i),oe&&oe()},R=(O,q)=>{O._isLeaving=!1,nt(O,h),nt(O,w),nt(O,m),q&&q()},z=O=>(q,oe)=>{const fe=O?N:k,H=()=>M(q,O,oe);tt(fe,[q,H]),ws(()=>{nt(q,O?c:o),Ve(q,O?f:l),vs(fe)||Cs(q,r,T,H)})};return ue(t,{onBeforeEnter(O){tt(B,[O]),Ve(O,o),Ve(O,i)},onBeforeAppear(O){tt(K,[O]),Ve(O,c),Ve(O,a)},onEnter:z(!1),onAppear:z(!0),onLeave(O,q){O._isLeaving=!0;const oe=()=>R(O,q);Ve(O,h),wc(),Ve(O,m),ws(()=>{O._isLeaving&&(nt(O,h),Ve(O,w),vs(p)||Cs(O,r,L,oe))}),tt(p,[O,oe])},onEnterCancelled(O){M(O,!1),tt(y,[O])},onAppearCancelled(O){M(O,!0),tt(v,[O])},onLeaveCancelled(O){R(O),tt(F,[O])}})}function _c(e){if(e==null)return null;if(ee(e))return[Yn(e.enter),Yn(e.leave)];{const t=Yn(e);return[t,t]}}function Yn(e){return _i(e)}function Ve(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Wt]||(e[Wt]=new Set)).add(t)}function nt(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Wt];n&&(n.delete(t),n.size||(e[Wt]=void 0))}function ws(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let bc=0;function Cs(e,t,n,r){const s=e._endId=++bc,o=()=>{s===e._endId&&r()};if(n)return setTimeout(o,n);const{type:i,timeout:l,propCount:c}=vc(e,t);if(!i)return r();const a=i+"end";let f=0;const h=()=>{e.removeEventListener(a,m),o()},m=w=>{w.target===e&&++f>=c&&h()};setTimeout(()=>{f(n[E]||"").split(", "),s=r(`${We}Delay`),o=r(`${We}Duration`),i=Es(s,o),l=r(`${Pt}Delay`),c=r(`${Pt}Duration`),a=Es(l,c);let f=null,h=0,m=0;t===We?i>0&&(f=We,h=i,m=o.length):t===Pt?a>0&&(f=Pt,h=a,m=c.length):(h=Math.max(i,a),f=h>0?i>a?We:Pt:null,m=f?f===We?o.length:c.length:0);const w=f===We&&/\b(transform|all)(,|$)/.test(r(`${We}Property`).toString());return{type:f,timeout:h,propCount:m,hasTransform:w}}function Es(e,t){for(;e.lengthxs(n)+xs(e[r])))}function xs(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function wc(){return document.body.offsetHeight}function Cc(e,t,n){const r=e[Wt];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Ec=Symbol("_vod");function xc(e,t,n){const r=e.style,s=ne(n);if(n&&!s){if(t&&!ne(t))for(const o in t)n[o]==null&&pr(r,o,"");for(const o in n)pr(r,o,n[o])}else{const o=r.display;s?t!==n&&(r.cssText=n):t&&e.removeAttribute("style"),Ec in e&&(r.display=o)}}const Ts=/\s*!important$/;function pr(e,t,n){if(U(n))n.forEach(r=>pr(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Tc(e,t);Ts.test(n)?e.setProperty(ft(r),n.replace(Ts,""),"important"):e[r]=n}}const As=["Webkit","Moz","ms"],Jn={};function Tc(e,t){const n=Jn[t];if(n)return n;let r=Ne(t);if(r!=="filter"&&r in e)return Jn[t]=r;r=Rn(r);for(let s=0;sXn||(Mc.then(()=>Xn=0),Xn=Date.now());function Ic(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;xe(Lc(r,n.value),t,5,[r])};return n.value=e,n.attached=Fc(),n}function Lc(e,t){if(U(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const Ps=/^on[a-z]/,Nc=(e,t,n,r,s=!1,o,i,l,c)=>{t==="class"?Cc(e,r,s):t==="style"?xc(e,n,r):zt(t)?yr(t)||Oc(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Hc(e,t,r,s))?Sc(e,t,r,o,i,l,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Ac(e,t,r,s))};function Hc(e,t,n,r){return r?!!(t==="innerHTML"||t==="textContent"||t in e&&Ps.test(t)&&W(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Ps.test(t)&&ne(n)?!1:t in e}const Ms=e=>{const t=e.props["onUpdate:modelValue"]||!1;return U(t)?n=>hn(t,n):t};function $c(e){e.target.composing=!0}function Fs(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const Qn=Symbol("_assign"),Xa={created(e,{modifiers:{lazy:t,trim:n,number:r}},s){e[Qn]=Ms(s);const o=r||s.props&&s.props.type==="number";gt(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),o&&(l=er(l)),e[Qn](l)}),n&>(e,"change",()=>{e.value=e.value.trim()}),t||(gt(e,"compositionstart",$c),gt(e,"compositionend",Fs),gt(e,"change",Fs))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:s}},o){if(e[Qn]=Ms(o),e.composing||document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===t||(s||e.type==="number")&&er(e.value)===t))return;const i=t??"";e.value!==i&&(e.value=i)}},jc=["ctrl","shift","alt","meta"],Dc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>jc.some(n=>e[`${n}Key`]&&!t.includes(n))},Qa=(e,t)=>(n,...r)=>{for(let s=0;sn=>{if(!("key"in n))return;const r=ft(n.key);if(t.some(s=>s===r||Bc[s]===r))return e(n)},zo=ue({patchProp:Nc},mc);let Dt,Is=!1;function kc(){return Dt||(Dt=Yl(zo))}function Uc(){return Dt=Is?Dt:Jl(zo),Is=!0,Dt}const Ga=(...e)=>{const t=kc().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=Yo(r);if(!s)return;const o=t._component;!W(o)&&!o.render&&!o.template&&(o.template=s.innerHTML),s.innerHTML="";const i=n(s,!1,s instanceof SVGElement);return s instanceof Element&&(s.removeAttribute("v-cloak"),s.setAttribute("data-v-app","")),i},t},eu=(...e)=>{const t=Uc().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=Yo(r);if(s)return n(s,!0,s instanceof SVGElement)},t};function Yo(e){return ne(e)?document.querySelector(e):e}const tu=(e,t)=>{const n=e.__vccOpts||e;for(const[r,s]of t)n[r]=s;return n},Kc="modulepreload",Wc=function(e){return"/"+e},Ls={},nu=function(t,n,r){if(!n||n.length===0)return t();const s=document.getElementsByTagName("link");return Promise.all(n.map(o=>{if(o=Wc(o),o in Ls)return;Ls[o]=!0;const i=o.endsWith(".css"),l=i?'[rel="stylesheet"]':"";if(!!r)for(let f=s.length-1;f>=0;f--){const h=s[f];if(h.href===o&&(!i||h.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${l}`))return;const a=document.createElement("link");if(a.rel=i?"stylesheet":Kc,i||(a.as="script",a.crossOrigin=""),a.href=o,document.head.appendChild(a),i)return new Promise((f,h)=>{a.addEventListener("load",f),a.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t()).catch(o=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=o,window.dispatchEvent(i),!i.defaultPrevented)throw o})},Vc=window.__VP_SITE_DATA__;function kr(e){return Qs()?(Si(e),!0):!1}function Pe(e){return typeof e=="function"?e():Mr(e)}function ru(e,t){const n=(t==null?void 0:t.computedGetter)===!1?Mr:Pe;return function(...r){return ie(()=>e.apply(this,r.map(s=>n(s))))}}const Jo=typeof window<"u"&&typeof document<"u",qc=Object.prototype.toString,zc=e=>qc.call(e)==="[object Object]",Vt=()=>{},Ns=Yc();function Yc(){var e;return Jo&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent)}function Jc(e,t){function n(...r){return new Promise((s,o)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(s).catch(o)})}return n}const Xo=e=>e();function Xc(e,t={}){let n,r,s=Vt;const o=l=>{clearTimeout(l),s(),s=Vt};return l=>{const c=Pe(e),a=Pe(t.maxWait);return n&&o(n),c<=0||a!==void 0&&a<=0?(r&&(o(r),r=null),Promise.resolve(l())):new Promise((f,h)=>{s=t.rejectOnCancel?h:f,a&&!r&&(r=setTimeout(()=>{n&&o(n),r=null,f(l())},a)),n=setTimeout(()=>{r&&o(r),r=null,f(l())},c)})}}function Qc(e=Xo){const t=ae(!0);function n(){t.value=!1}function r(){t.value=!0}const s=(...o)=>{t.value&&e(...o)};return{isActive:Mn(t),pause:n,resume:r,eventFilter:s}}function Qo(...e){if(e.length!==1)return nl(...e);const t=e[0];return typeof t=="function"?Mn(Gi(()=>({get:t,set:Vt}))):ae(t)}function Zo(e,t,n={}){const{eventFilter:r=Xo,...s}=n;return Xe(e,Jc(r,t),s)}function Zc(e,t,n={}){const{eventFilter:r,...s}=n,{eventFilter:o,pause:i,resume:l,isActive:c}=Qc(r);return{stop:Zo(e,t,{...s,eventFilter:o}),pause:i,resume:l,isActive:c}}function Gc(e,t=!0){Bn()?Rt(e):t?e():Fn(e)}function su(e,t,n={}){const{debounce:r=0,maxWait:s=void 0,...o}=n;return Zo(e,t,{...o,eventFilter:Xc(r,{maxWait:s})})}function ou(e,t,n){let r;ce(n)?r={evaluating:n}:r=n||{};const{lazy:s=!1,evaluating:o=void 0,shallow:i=!0,onError:l=Vt}=r,c=ae(!s),a=i?Pr(t):ae(t);let f=0;return Ir(async h=>{if(!c.value)return;f++;const m=f;let w=!1;o&&Promise.resolve().then(()=>{o.value=!0});try{const E=await e(T=>{h(()=>{o&&(o.value=!1),w||T()})});m===f&&(a.value=E)}catch(E){l(E)}finally{o&&m===f&&(o.value=!1),w=!0}}),s?ie(()=>(c.value=!0,a.value)):a}function Go(e){var t;const n=Pe(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Be=Jo?window:void 0;function qt(...e){let t,n,r,s;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,s]=e,t=Be):[t,n,r,s]=e,!t)return Vt;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const o=[],i=()=>{o.forEach(f=>f()),o.length=0},l=(f,h,m,w)=>(f.addEventListener(h,m,w),()=>f.removeEventListener(h,m,w)),c=Xe(()=>[Go(t),Pe(s)],([f,h])=>{if(i(),!f)return;const m=zc(h)?{...h}:h;o.push(...n.flatMap(w=>r.map(E=>l(f,w,E,m))))},{immediate:!0,flush:"post"}),a=()=>{c(),i()};return kr(a),a}function ea(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function iu(...e){let t,n,r={};e.length===3?(t=e[0],n=e[1],r=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],r=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:s=Be,eventName:o="keydown",passive:i=!1,dedupe:l=!1}=r,c=ea(t);return qt(s,o,f=>{f.repeat&&Pe(l)||c(f)&&n(f)},i)}function ta(){const e=ae(!1);return Bn()&&Rt(()=>{e.value=!0}),e}function na(e){const t=ta();return ie(()=>(t.value,!!e()))}function ra(e,t={}){const{window:n=Be}=t,r=na(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let s;const o=ae(!1),i=a=>{o.value=a.matches},l=()=>{s&&("removeEventListener"in s?s.removeEventListener("change",i):s.removeListener(i))},c=Ir(()=>{r.value&&(l(),s=n.matchMedia(Pe(e)),"addEventListener"in s?s.addEventListener("change",i):s.addListener(i),o.value=s.matches)});return kr(()=>{c(),l(),s=void 0}),o}const an=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},un="__vueuse_ssr_handlers__",sa=oa();function oa(){return un in an||(an[un]=an[un]||{}),an[un]}function ei(e,t){return sa[e]||t}function ia(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const la={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Hs="vueuse-storage";function Ur(e,t,n,r={}){var s;const{flush:o="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:a=!1,shallow:f,window:h=Be,eventFilter:m,onError:w=v=>{console.error(v)}}=r,E=(f?Pr:ae)(t);if(!n)try{n=ei("getDefaultStorage",()=>{var v;return(v=Be)==null?void 0:v.localStorage})()}catch(v){w(v)}if(!n)return E;const T=Pe(t),L=ia(T),B=(s=r.serializer)!=null?s:la[L],{pause:k,resume:y}=Zc(E,()=>p(E.value),{flush:o,deep:i,eventFilter:m});return h&&l&&(qt(h,"storage",N),qt(h,Hs,K)),N(),E;function p(v){try{if(v==null)n.removeItem(e);else{const M=B.write(v),R=n.getItem(e);R!==M&&(n.setItem(e,M),h&&h.dispatchEvent(new CustomEvent(Hs,{detail:{key:e,oldValue:R,newValue:M,storageArea:n}})))}}catch(M){w(M)}}function F(v){const M=v?v.newValue:n.getItem(e);if(M==null)return c&&T!==null&&n.setItem(e,B.write(T)),T;if(!v&&a){const R=B.read(M);return typeof a=="function"?a(R,T):L==="object"&&!Array.isArray(R)?{...T,...R}:R}else return typeof M!="string"?M:B.read(M)}function K(v){N(v.detail)}function N(v){if(!(v&&v.storageArea!==n)){if(v&&v.key==null){E.value=T;return}if(!(v&&v.key!==e)){k();try{(v==null?void 0:v.newValue)!==B.write(E.value)&&(E.value=F(v))}catch(M){w(M)}finally{v?Fn(y):y()}}}}}function ca(e){return ra("(prefers-color-scheme: dark)",e)}function aa(e={}){const{selector:t="html",attribute:n="class",initialValue:r="auto",window:s=Be,storage:o,storageKey:i="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:a,disableTransition:f=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},m=ca({window:s}),w=ie(()=>m.value?"dark":"light"),E=c||(i==null?Qo(r):Ur(i,r,o,{window:s,listenToStorageChanges:l})),T=ie(()=>E.value==="auto"?w.value:E.value),L=ei("updateHTMLAttrs",(p,F,K)=>{const N=typeof p=="string"?s==null?void 0:s.document.querySelector(p):Go(p);if(!N)return;let v;if(f){v=s.document.createElement("style");const M="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";v.appendChild(document.createTextNode(M)),s.document.head.appendChild(v)}if(F==="class"){const M=K.split(/\s/g);Object.values(h).flatMap(R=>(R||"").split(/\s/g)).filter(Boolean).forEach(R=>{M.includes(R)?N.classList.add(R):N.classList.remove(R)})}else N.setAttribute(F,K);f&&(s.getComputedStyle(v).opacity,document.head.removeChild(v))});function B(p){var F;L(t,n,(F=h[p])!=null?F:p)}function k(p){e.onChanged?e.onChanged(p,B):B(p)}Xe(T,k,{flush:"post",immediate:!0}),Gc(()=>k(T.value));const y=ie({get(){return a?E.value:T.value},set(p){E.value=p}});try{return Object.assign(y,{store:E,system:w,state:T})}catch{return y}}function ua(e={}){const{valueDark:t="dark",valueLight:n=""}=e,r=aa({...e,onChanged:(o,i)=>{var l;e.onChanged?(l=e.onChanged)==null||l.call(e,o==="dark",i,o):i(o)},modes:{dark:t,light:n}});return ie({get(){return r.value==="dark"},set(o){const i=o?"dark":"light";r.system.value===i?r.value="auto":r.value=i}})}function Zn(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function lu(e,t,n={}){const{window:r=Be}=n;return Ur(e,t,r==null?void 0:r.localStorage,n)}function ti(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}function cu(e,t=!1){const n=ae(t);let r=null,s;Xe(Qo(e),l=>{const c=Zn(Pe(l));if(c){const a=c;s=a.style.overflow,n.value&&(a.style.overflow="hidden")}},{immediate:!0});const o=()=>{const l=Zn(Pe(e));!l||n.value||(Ns&&(r=qt(l,"touchmove",c=>{fa(c)},{passive:!1})),l.style.overflow="hidden",n.value=!0)},i=()=>{const l=Zn(Pe(e));!l||!n.value||(Ns&&(r==null||r()),l.style.overflow=s,n.value=!1)};return kr(i),ie({get(){return n.value},set(l){l?o():i()}})}function au(e,t,n={}){const{window:r=Be}=n;return Ur(e,t,r==null?void 0:r.sessionStorage,n)}function uu(e={}){const{window:t=Be}=e;if(!t)return{x:ae(0),y:ae(0)};const n=ae(t.scrollX),r=ae(t.scrollY);return qt(t,"scroll",()=>{n.value=t.scrollX,r.value=t.scrollY},{capture:!1,passive:!0}),{x:n,y:r}}const ni=/^[a-z]+:/i,da="vitepress-theme-appearance",ri=/#.*$/,ha=/(index)?\.(md|html)$/,Ee=typeof document<"u",si={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function pa(e,t,n=!1){if(t===void 0)return!1;if(e=$s(`/${e}`),n)return new RegExp(t).test(e);if($s(t)!==e)return!1;const r=t.match(ri);return r?(Ee?location.hash:"")===r[0]:!0}function $s(e){return decodeURI(e).replace(ri,"").replace(ha,"")}function ga(e){return ni.test(e)}function ma(e,t){var r,s,o,i,l,c,a;const n=Object.keys(e.locales).find(f=>f!=="root"&&!ga(f)&&pa(t,`/${f}/`,!0))||"root";return Object.assign({},e,{localeIndex:n,lang:((r=e.locales[n])==null?void 0:r.lang)??e.lang,dir:((s=e.locales[n])==null?void 0:s.dir)??e.dir,title:((o=e.locales[n])==null?void 0:o.title)??e.title,titleTemplate:((i=e.locales[n])==null?void 0:i.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:ii(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(a=e.locales[n])==null?void 0:a.themeConfig}})}function oi(e,t){const n=t.title||e.title,r=t.titleTemplate??e.titleTemplate;if(typeof r=="string"&&r.includes(":title"))return r.replace(/:title/g,n);const s=ya(e.title,r);return`${n}${s}`}function ya(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function _a(e,t){const[n,r]=t;if(n!=="meta")return!1;const s=Object.entries(r)[0];return s==null?!1:e.some(([o,i])=>o===n&&i[s[0]]===s[1])}function ii(e,t){return[...e.filter(n=>!_a(t,n)),...t]}const ba=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,va=/^[a-z]:/i;function js(e){const t=va.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(ba,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const wa=Symbol(),at=Pr(Vc);function fu(e){const t=ie(()=>ma(at.value,e.data.relativePath)),n=t.value.appearance,r=n==="force-dark"?ae(!0):n?ua({storageKey:da,initialValue:()=>typeof n=="string"?n:"auto",...typeof n=="object"?n:{}}):ae(!1);return{site:t,theme:ie(()=>t.value.themeConfig),page:ie(()=>e.data),frontmatter:ie(()=>e.data.frontmatter),params:ie(()=>e.data.params),lang:ie(()=>t.value.lang),dir:ie(()=>t.value.dir),localeIndex:ie(()=>t.value.localeIndex||"root"),title:ie(()=>oi(t.value,e.data)),description:ie(()=>e.data.description||t.value.description),isDark:r}}function Ca(){const e=wt(wa);if(!e)throw new Error("vitepress data not properly injected in app");return e}function Ea(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Ds(e){return ni.test(e)||!e.startsWith("/")?e:Ea(at.value.base,e)}function xa(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),Ee){const n="/";t=js(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let r=__VP_HASH_MAP__[t.toLowerCase()];if(r||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",r=__VP_HASH_MAP__[t.toLowerCase()]),!r)return null;t=`${n}assets/${t}.${r}.js`}else t=`./${js(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let gn=[];function du(e){gn.push(e),jn(()=>{gn=gn.filter(t=>t!==e)})}const Ta=Symbol(),li="http://a.com",Aa=()=>({path:"/",component:null,data:si});function hu(e,t){const n=Pn(Aa()),r={route:n,go:s};async function s(l=Ee?location.href:"/"){var c,a;l=gr(l),await((c=r.onBeforeRouteChange)==null?void 0:c.call(r,l))!==!1&&(Us(l),await i(l),await((a=r.onAfterRouteChanged)==null?void 0:a.call(r,l)))}let o=null;async function i(l,c=0,a=!1){var m;if(await((m=r.onBeforePageLoad)==null?void 0:m.call(r,l))===!1)return;const f=new URL(l,li),h=o=f.pathname;try{let w=await e(h);if(!w)throw new Error(`Page not found: ${h}`);if(o===h){o=null;const{default:E,__pageData:T}=w;if(!E)throw new Error(`Invalid route component: ${E}`);n.path=Ee?h:Ds(h),n.component=Lt(E),n.data=Lt(T),Ee&&Fn(()=>{let L=at.value.base+T.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!at.value.cleanUrls&&!L.endsWith("/")&&(L+=".html"),L!==f.pathname&&(f.pathname=L,l=L+f.search+f.hash,history.replaceState(null,"",l)),f.hash&&!c){let B=null;try{B=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(k){console.warn(k)}if(B){Bs(B,f.hash);return}}window.scrollTo(0,c)})}}catch(w){if(!/fetch|Page not found/.test(w.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(w),!a)try{const E=await fetch(at.value.base+"hashmap.json");window.__VP_HASH_MAP__=await E.json(),await i(l,c,!0);return}catch{}o===h&&(o=null,n.path=Ee?h:Ds(h),n.component=t?Lt(t):null,n.data=si)}}return Ee&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const a=l.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:f}=a,{href:h,origin:m,pathname:w,hash:E,search:T}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),L=window.location,B=w.match(/\.\w+$/);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&!f&&m===L.origin&&!(B&&B[0]!==".html")&&(l.preventDefault(),w===L.pathname&&T===L.search?(E!==L.hash&&(history.pushState(null,"",E),window.dispatchEvent(new Event("hashchange"))),E?Bs(a,E,a.classList.contains("header-anchor")):(Us(h),window.scrollTo(0,0))):s(h))}},{capture:!0}),window.addEventListener("popstate",l=>{i(gr(location.href),l.state&&l.state.scrollPosition||0)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),r}function Sa(){const e=wt(Ta);if(!e)throw new Error("useRouter() is called without provider.");return e}function ci(){return Sa().route}function Bs(e,t,n=!1){let r=null;try{r=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(s){console.warn(s)}if(r){let a=function(){!n||Math.abs(c-window.scrollY)>window.innerHeight?window.scrollTo(0,c):window.scrollTo({left:0,top:c,behavior:"smooth"})},s=at.value.scrollOffset,o=0,i=24;if(typeof s=="object"&&"padding"in s&&(i=s.padding,s=s.selector),typeof s=="number")o=s;else if(typeof s=="string")o=ks(s,i);else if(Array.isArray(s))for(const f of s){const h=ks(f,i);if(h){o=h;break}}const l=parseInt(window.getComputedStyle(r).paddingTop,10),c=window.scrollY+r.getBoundingClientRect().top-o+l;requestAnimationFrame(a)}}function ks(e,t){const n=document.querySelector(e);if(!n)return 0;const r=n.getBoundingClientRect().bottom;return r<0?0:r+t}function Us(e){Ee&&e!==gr(location.href)&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",e))}function gr(e){const t=new URL(e,li);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),at.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const Ks=()=>gn.forEach(e=>e()),pu=Lr({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=ci(),{site:n}=Ca();return()=>hr(e.as,n.value.contentProps??{style:{position:"relative"}},[t.component?hr(t.component,{onVnodeMounted:Ks,onVnodeUpdated:Ks}):"404 Page Not Found"])}}),gu=Lr({setup(e,{slots:t}){const n=ae(!1);return Rt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function mu(){Ee&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const r=(n=t.parentElement)==null?void 0:n.parentElement;if(!r)return;const s=Array.from(r.querySelectorAll("input")).indexOf(t);if(s<0)return;const o=r.querySelector(".blocks");if(!o)return;const i=Array.from(o.children).find(a=>a.classList.contains("active"));if(!i)return;const l=o.children[s];if(!l||i===l)return;i.classList.remove("active"),l.classList.add("active");const c=r==null?void 0:r.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function yu(){if(Ee){const e=new WeakMap;window.addEventListener("click",t=>{var r;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const s=n.parentElement,o=(r=n.nextElementSibling)==null?void 0:r.nextElementSibling;if(!s||!o)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(s.className);let l="";o.querySelectorAll("span.line:not(.diff.remove)").forEach(c=>l+=(c.textContent||"")+` +`),l=l.slice(0,-1),i&&(l=l.replace(/^ *(\$|>) /gm,"").trim()),Ra(l).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const c=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,c)})}})}}async function Ra(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const r=document.getSelection(),s=r?r.rangeCount>0&&r.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),s&&(r.removeAllRanges(),r.addRange(s)),n&&n.focus()}}function _u(e,t){let n=[],r=!0;const s=o=>{if(r){r=!1;return}const i=o.map(Ws);n.forEach((l,c)=>{const a=i.findIndex(f=>f==null?void 0:f.isEqualNode(l??null));a!==-1?delete i[a]:(l==null||l.remove(),delete n[c])}),i.forEach(l=>l&&document.head.appendChild(l)),n=[...n,...i].filter(Boolean)};Ir(()=>{const o=e.data,i=t.value,l=o&&o.description,c=o&&o.frontmatter.head||[],a=oi(i,o);a!==document.title&&(document.title=a);const f=l||i.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==f&&h.setAttribute("content",f):Ws(["meta",{name:"description",content:f}]),s(ii(i.head,Pa(c)))})}function Ws([e,t,n]){const r=document.createElement(e);for(const s in t)r.setAttribute(s,t[s]);return n&&(r.innerHTML=n),e==="script"&&!t.async&&(r.async=!1),r}function Oa(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function Pa(e){return e.filter(t=>!Oa(t))}const Gn=new Set,ai=()=>document.createElement("link"),Ma=e=>{const t=ai();t.rel="prefetch",t.href=e,document.head.appendChild(t)},Fa=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let fn;const Ia=Ee&&(fn=ai())&&fn.relList&&fn.relList.supports&&fn.relList.supports("prefetch")?Ma:Fa;function bu(){if(!Ee||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const r=()=>{n&&n.disconnect(),n=new IntersectionObserver(o=>{o.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!Gn.has(c)){Gn.add(c);const a=xa(c);a&&Ia(a)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(o=>{const{hostname:i,pathname:l}=new URL(o.href instanceof SVGAnimatedString?o.href.animVal:o.href,o.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||o.target!=="_blank"&&i===location.hostname&&(l!==location.pathname?n.observe(o):Gn.add(l))})})};Rt(r);const s=ci();Xe(()=>s.path,r),jn(()=>{n&&n.disconnect()})}export{Za as $,$a as A,Sl as B,Ba as C,Ua as D,Pr as E,me as F,du as G,re as H,ka as I,ni as J,ci as K,rc as L,wt as M,vr as N,Fn as O,uu as P,Ya as Q,Mn as R,ru as S,Vo as T,nl as U,iu as V,Da as W,nu as X,cu as Y,kl as Z,tu as _,ko as a,Wa as a0,Qa as a1,Va as a2,_u as a3,Ta as a4,fu as a5,wa as a6,pu as a7,gu as a8,at as a9,eu as aa,hu as ab,xa as ac,bu as ad,yu as ae,mu as af,hr as ag,Go as ah,kr as ai,ou as aj,au as ak,lu as al,su as am,Sa as an,qt as ao,Co as ap,ja as aq,Xa as ar,ce as as,qa as at,Lt as au,Ga as av,jo as b,za as c,Lr as d,Ja as e,Ds as f,ie as g,ae as h,ga as i,Rt as j,Bo as k,Mr as l,Ha as m,wr as n,Ho as o,Na as p,pa as q,Ka as r,Ee as s,La as t,Ca as u,ra as v,dl as w,Xe as x,Ir as y,jn as z}; diff --git a/assets/chunks/theme.802a1aee.js b/assets/chunks/theme.802a1aee.js new file mode 100644 index 00000000..a89b8222 --- /dev/null +++ b/assets/chunks/theme.802a1aee.js @@ -0,0 +1 @@ +import{d as b,o as a,c as i,r as u,n as T,a as x,t as L,_ as m,b as $,w as v,T as ce,e as f,u as ze,i as De,f as ue,g as k,h as M,j as G,k as c,l,p as H,m as z,q as O,s as q,v as re,x as U,y as te,z as de,A as Ve,B as Ee,C as j,F as N,D as A,E as _e,G as Y,H as h,I as F,J as we,K as se,L as Z,M as ne,N as Fe,O as Oe,P as Le,Q as Ge,R as Ue,S as je,U as Ke,V as ke,W as Re,X as qe,Y as Se,Z as Me,$ as We,a0 as Ye,a1 as Je,a2 as Xe}from"./framework.0e8ae64e.js";const Ze=b({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(s){return(e,t)=>(a(),i("span",{class:T(["VPBadge",e.type])},[u(e.$slots,"default",{},()=>[x(L(e.text),1)],!0)],2))}});const Qe=m(Ze,[["__scopeId","data-v-ea5b2908"]]),et={key:0,class:"VPBackdrop"},tt=b({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(s){return(e,t)=>(a(),$(ce,{name:"fade"},{default:v(()=>[e.show?(a(),i("div",et)):f("",!0)]),_:1}))}});const st=m(tt,[["__scopeId","data-v-54a304ca"]]),P=ze;function nt(s,e){let t,n=!1;return()=>{t&&clearTimeout(t),n?t=setTimeout(s,e):(s(),(n=!0)&&setTimeout(()=>n=!1,e))}}function le(s){return/^\//.test(s)?s:`/${s}`}function J(s){const{pathname:e,search:t,hash:n,protocol:o}=new URL(s,"http://a.com");if(De(s)||s.startsWith("#")||!o.startsWith("http")||/\.(?!html|md)\w+($|\?)/i.test(s))return s;const{site:r}=P(),d=e.endsWith("/")||e.endsWith(".html")?s:s.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,r.value.cleanUrls?"":".html")}${t}${n}`);return ue(d)}function X({removeCurrent:s=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:o,theme:r}=P(),d=k(()=>{var _,g;return{label:(_=t.value.locales[n.value])==null?void 0:_.label,link:((g=t.value.locales[n.value])==null?void 0:g.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:k(()=>Object.entries(t.value.locales).flatMap(([_,g])=>s&&d.value.label===g.label?[]:{text:g.label,link:ot(g.link||(_==="root"?"/":`/${_}/`),r.value.i18nRouting!==!1&&e,o.value.relativePath.slice(d.value.link.length-1),!t.value.cleanUrls)})),currentLang:d}}function ot(s,e,t,n){return e?s.replace(/\/$/,"")+le(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,n?".html":"")):s}const at=s=>(H("data-v-b9c0c15a"),s=s(),z(),s),rt={class:"NotFound"},lt={class:"code"},it={class:"title"},ct=at(()=>c("div",{class:"divider"},null,-1)),ut={class:"quote"},dt={class:"action"},_t=["href","aria-label"],vt=b({__name:"NotFound",setup(s){const{site:e,theme:t}=P(),{localeLinks:n}=X({removeCurrent:!1}),o=M("/");return G(()=>{var d;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");n.value.length&&(o.value=((d=n.value.find(({link:p})=>p.startsWith(r)))==null?void 0:d.link)||n.value[0].link)}),(r,d)=>{var p,_,g,V,y;return a(),i("div",rt,[c("p",lt,L(((p=l(t).notFound)==null?void 0:p.code)??"404"),1),c("h1",it,L(((_=l(t).notFound)==null?void 0:_.title)??"PAGE NOT FOUND"),1),ct,c("blockquote",ut,L(((g=l(t).notFound)==null?void 0:g.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),c("div",dt,[c("a",{class:"link",href:l(ue)(o.value),"aria-label":((V=l(t).notFound)==null?void 0:V.linkLabel)??"go to home"},L(((y=l(t).notFound)==null?void 0:y.linkText)??"Take me home"),9,_t)])])}}});const pt=m(vt,[["__scopeId","data-v-b9c0c15a"]]);function Ne(s,e){if(Array.isArray(s))return Q(s);if(s==null)return[];e=le(e);const t=Object.keys(s).sort((o,r)=>r.split("/").length-o.split("/").length).find(o=>e.startsWith(le(o))),n=t?s[t]:[];return Array.isArray(n)?Q(n):Q(n.items,n.base)}function ht(s){const e=[];let t=0;for(const n in s){const o=s[n];if(o.items){t=e.push(o);continue}e[t]||e.push({items:[]}),e[t].items.push(o)}return e}function ft(s){const e=[];function t(n){for(const o of n)o.text&&o.link&&e.push({text:o.text,link:o.link,docFooterText:o.docFooterText}),o.items&&t(o.items)}return t(s),e}function ie(s,e){return Array.isArray(e)?e.some(t=>ie(s,t)):O(s,e.link)?!0:e.items?ie(s,e.items):!1}function Q(s,e){return[...s].map(t=>{const n={...t},o=n.base||e;return o&&n.link&&(n.link=o+n.link),n.items&&(n.items=Q(n.items,o)),n})}function D(){const{frontmatter:s,page:e,theme:t}=P(),n=re("(min-width: 960px)"),o=M(!1),r=k(()=>{const B=t.value.sidebar,w=e.value.relativePath;return B?Ne(B,w):[]}),d=M(r.value);U(r,(B,w)=>{JSON.stringify(B)!==JSON.stringify(w)&&(d.value=r.value)});const p=k(()=>s.value.sidebar!==!1&&d.value.length>0&&s.value.layout!=="home"),_=k(()=>g?s.value.aside==null?t.value.aside==="left":s.value.aside==="left":!1),g=k(()=>s.value.layout==="home"?!1:s.value.aside!=null?!!s.value.aside:t.value.aside!==!1),V=k(()=>p.value&&n.value),y=k(()=>p.value?ht(d.value):[]);function I(){o.value=!0}function S(){o.value=!1}function C(){o.value?S():I()}return{isOpen:o,sidebar:d,sidebarGroups:y,hasSidebar:p,hasAside:g,leftAside:_,isSidebarEnabled:V,open:I,close:S,toggle:C}}function mt(s,e){let t;te(()=>{t=s.value?document.activeElement:void 0}),G(()=>{window.addEventListener("keyup",n)}),de(()=>{window.removeEventListener("keyup",n)});function n(o){o.key==="Escape"&&s.value&&(e(),t==null||t.focus())}}const Ie=M(q?location.hash:"");q&&window.addEventListener("hashchange",()=>{Ie.value=location.hash});function gt(s){const{page:e}=P(),t=M(!1),n=k(()=>s.value.collapsed!=null),o=k(()=>!!s.value.link),r=M(!1),d=()=>{r.value=O(e.value.relativePath,s.value.link)};U([e,s,Ie],d),G(d);const p=k(()=>r.value?!0:s.value.items?ie(e.value.relativePath,s.value.items):!1),_=k(()=>!!(s.value.items&&s.value.items.length));te(()=>{t.value=!!(n.value&&s.value.collapsed)}),Ve(()=>{(r.value||p.value)&&(t.value=!1)});function g(){n.value&&(t.value=!t.value)}return{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:p,hasChildren:_,toggle:g}}function bt(){const{hasSidebar:s}=D(),e=re("(min-width: 960px)"),t=re("(min-width: 1280px)");return{isAsideEnabled:k(()=>!t.value&&!e.value?!1:s.value?t.value:e.value)}}const $t=71;function ve(s){return typeof s.outline=="object"&&!Array.isArray(s.outline)&&s.outline.label||s.outlineTitle||"On this page"}function pe(s){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const n=Number(t.tagName[1]);return{title:kt(t),link:"#"+t.id,level:n}});return yt(e,s)}function kt(s){let e="";for(const t of s.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function yt(s,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[n,o]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;s=s.filter(d=>d.level>=n&&d.level<=o);const r=[];e:for(let d=0;d=0;_--){const g=s[_];if(g.level{requestAnimationFrame(r),window.addEventListener("scroll",n)}),Ee(()=>{d(location.hash)}),de(()=>{window.removeEventListener("scroll",n)});function r(){if(!t.value)return;const p=[].slice.call(s.value.querySelectorAll(".outline-link")),_=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(S=>p.some(C=>C.hash===S.hash&&S.offsetParent!==null)),g=window.scrollY,V=window.innerHeight,y=document.body.offsetHeight,I=Math.abs(g+V-y)<1;if(_.length&&I){d(_[_.length-1].hash);return}for(let S=0;S<_.length;S++){const C=_[S],B=_[S+1],[w,K]=Vt(S,C,B);if(w){d(K);return}}}function d(p){o&&o.classList.remove("active"),p==null?o=null:o=s.value.querySelector(`a[href="${decodeURIComponent(p)}"]`);const _=o;_?(_.classList.add("active"),e.value.style.top=_.offsetTop+33+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function ye(s){return s.parentElement.offsetTop-$t}function Vt(s,e,t){const n=window.scrollY;return s===0&&n===0?[!0,null]:n{const o=j("VPDocOutlineItem",!0);return a(),i("ul",{class:T(t.root?"root":"nested")},[(a(!0),i(N,null,A(t.headers,({children:r,link:d,title:p})=>(a(),i("li",null,[c("a",{class:"outline-link",href:d,onClick:e,title:p},L(p),9,wt),r!=null&&r.length?(a(),$(o,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}});const he=m(Lt,[["__scopeId","data-v-463da30f"]]),St=s=>(H("data-v-3a6c4994"),s=s(),z(),s),Mt={class:"content"},Nt={class:"outline-title",role:"heading","aria-level":"2"},It={"aria-labelledby":"doc-outline-aria-label"},Tt=St(()=>c("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Ct=b({__name:"VPDocAsideOutline",setup(s){const{frontmatter:e,theme:t}=P(),n=_e([]);Y(()=>{n.value=pe(e.value.outline??t.value.outline)});const o=M(),r=M();return Pt(o,r),(d,p)=>(a(),i("div",{class:T(["VPDocAsideOutline",{"has-outline":n.value.length>0}]),ref_key:"container",ref:o,role:"navigation"},[c("div",Mt,[c("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),c("div",Nt,L(l(ve)(l(t))),1),c("nav",It,[Tt,h(he,{headers:n.value,root:!0},null,8,["headers"])])])],2))}});const Bt=m(Ct,[["__scopeId","data-v-3a6c4994"]]),At={class:"VPDocAsideCarbonAds"},xt=b({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(s){const e=()=>null;return(t,n)=>(a(),i("div",At,[h(l(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Ht=s=>(H("data-v-cb998dce"),s=s(),z(),s),zt={class:"VPDocAside"},Dt=Ht(()=>c("div",{class:"spacer"},null,-1)),Et=b({__name:"VPDocAside",setup(s){const{theme:e}=P();return(t,n)=>(a(),i("div",zt,[u(t.$slots,"aside-top",{},void 0,!0),u(t.$slots,"aside-outline-before",{},void 0,!0),h(Bt),u(t.$slots,"aside-outline-after",{},void 0,!0),Dt,u(t.$slots,"aside-ads-before",{},void 0,!0),l(e).carbonAds?(a(),$(xt,{key:0,"carbon-ads":l(e).carbonAds},null,8,["carbon-ads"])):f("",!0),u(t.$slots,"aside-ads-after",{},void 0,!0),u(t.$slots,"aside-bottom",{},void 0,!0)]))}});const Ft=m(Et,[["__scopeId","data-v-cb998dce"]]);function Ot(){const{theme:s,page:e}=P();return k(()=>{const{text:t="Edit this page",pattern:n=""}=s.value.editLink||{};let o;return typeof n=="function"?o=n(e.value):o=n.replace(/:path/g,e.value.filePath),{url:o,text:t}})}function Gt(){const{page:s,theme:e,frontmatter:t}=P();return k(()=>{var _,g,V,y,I,S,C,B;const n=Ne(e.value.sidebar,s.value.relativePath),o=ft(n),r=o.findIndex(w=>O(s.value.relativePath,w.link)),d=((_=e.value.docFooter)==null?void 0:_.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((g=e.value.docFooter)==null?void 0:g.next)===!1&&!t.value.next||t.value.next===!1;return{prev:d?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((V=o[r-1])==null?void 0:V.docFooterText)??((y=o[r-1])==null?void 0:y.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((I=o[r-1])==null?void 0:I.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((S=o[r+1])==null?void 0:S.docFooterText)??((C=o[r+1])==null?void 0:C.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((B=o[r+1])==null?void 0:B.link)}}})}const Ut={},jt={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Kt=c("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),Rt=c("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),qt=[Kt,Rt];function Wt(s,e){return a(),i("svg",jt,qt)}const Yt=m(Ut,[["render",Wt]]),E=b({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(s){const e=s,t=k(()=>e.tag??(e.href?"a":"span")),n=k(()=>e.href&&we.test(e.href));return(o,r)=>(a(),$(F(t.value),{class:T(["VPLink",{link:o.href,"vp-external-link-icon":n.value,"no-icon":o.noIcon}]),href:o.href?l(J)(o.href):void 0,target:o.target??(n.value?"_blank":void 0),rel:o.rel??(n.value?"noreferrer":void 0)},{default:v(()=>[u(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Jt={class:"VPLastUpdated"},Xt=["datetime"],Zt=b({__name:"VPDocFooterLastUpdated",setup(s){const{theme:e,page:t,frontmatter:n,lang:o}=P(),r=k(()=>new Date(n.value.lastUpdated??t.value.lastUpdated)),d=k(()=>r.value.toISOString()),p=M("");return G(()=>{te(()=>{var _,g,V;p.value=new Intl.DateTimeFormat((g=(_=e.value.lastUpdated)==null?void 0:_.formatOptions)!=null&&g.forceLocale?o.value:void 0,((V=e.value.lastUpdated)==null?void 0:V.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(_,g)=>{var V;return a(),i("p",Jt,[x(L(((V=l(e).lastUpdated)==null?void 0:V.text)||l(e).lastUpdatedText||"Last updated")+": ",1),c("time",{datetime:d.value},L(p.value),9,Xt)])}}});const Qt=m(Zt,[["__scopeId","data-v-19a7ae4e"]]),es={key:0,class:"VPDocFooter"},ts={key:0,class:"edit-info"},ss={key:0,class:"edit-link"},ns={key:1,class:"last-updated"},os={key:1,class:"prev-next"},as={class:"pager"},rs=["href"],ls=["innerHTML"],is=["innerHTML"],cs={class:"pager"},us=["href"],ds=["innerHTML"],_s=["innerHTML"],vs=b({__name:"VPDocFooter",setup(s){const{theme:e,page:t,frontmatter:n}=P(),o=Ot(),r=Gt(),d=k(()=>e.value.editLink&&n.value.editLink!==!1),p=k(()=>t.value.lastUpdated&&n.value.lastUpdated!==!1),_=k(()=>d.value||p.value||r.value.prev||r.value.next);return(g,V)=>{var y,I,S,C,B,w;return _.value?(a(),i("footer",es,[u(g.$slots,"doc-footer-before",{},void 0,!0),d.value||p.value?(a(),i("div",ts,[d.value?(a(),i("div",ss,[h(E,{class:"edit-link-button",href:l(o).url,"no-icon":!0},{default:v(()=>[h(Yt,{class:"edit-link-icon","aria-label":"edit icon"}),x(" "+L(l(o).text),1)]),_:1},8,["href"])])):f("",!0),p.value?(a(),i("div",ns,[h(Qt)])):f("",!0)])):f("",!0),(y=l(r).prev)!=null&&y.link||(I=l(r).next)!=null&&I.link?(a(),i("nav",os,[c("div",as,[(S=l(r).prev)!=null&&S.link?(a(),i("a",{key:0,class:"pager-link prev",href:l(J)(l(r).prev.link)},[c("span",{class:"desc",innerHTML:((C=l(e).docFooter)==null?void 0:C.prev)||"Previous page"},null,8,ls),c("span",{class:"title",innerHTML:l(r).prev.text},null,8,is)],8,rs)):f("",!0)]),c("div",cs,[(B=l(r).next)!=null&&B.link?(a(),i("a",{key:0,class:"pager-link next",href:l(J)(l(r).next.link)},[c("span",{class:"desc",innerHTML:((w=l(e).docFooter)==null?void 0:w.next)||"Next page"},null,8,ds),c("span",{class:"title",innerHTML:l(r).next.text},null,8,_s)],8,us)):f("",!0)])])):f("",!0)])):f("",!0)}}});const ps=m(vs,[["__scopeId","data-v-a2d931e4"]]),hs={},fs={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ms=c("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),gs=[ms];function bs(s,e){return a(),i("svg",fs,gs)}const fe=m(hs,[["render",bs]]),$s={key:0,class:"VPDocOutlineDropdown"},ks={key:0,class:"items"},ys=b({__name:"VPDocOutlineDropdown",setup(s){const{frontmatter:e,theme:t}=P(),n=M(!1);Y(()=>{n.value=!1});const o=_e([]);return Y(()=>{o.value=pe(e.value.outline??t.value.outline)}),(r,d)=>o.value.length>0?(a(),i("div",$s,[c("button",{onClick:d[0]||(d[0]=p=>n.value=!n.value),class:T({open:n.value})},[x(L(l(ve)(l(t)))+" ",1),h(fe,{class:"icon"})],2),n.value?(a(),i("div",ks,[h(he,{headers:o.value},null,8,["headers"])])):f("",!0)])):f("",!0)}});const Ps=m(ys,[["__scopeId","data-v-95bb0785"]]),Vs=s=>(H("data-v-a3c25e27"),s=s(),z(),s),ws={class:"container"},Ls=Vs(()=>c("div",{class:"aside-curtain"},null,-1)),Ss={class:"aside-container"},Ms={class:"aside-content"},Ns={class:"content"},Is={class:"content-container"},Ts={class:"main"},Cs=b({__name:"VPDoc",setup(s){const{theme:e}=P(),t=se(),{hasSidebar:n,hasAside:o,leftAside:r}=D(),d=k(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(p,_)=>{const g=j("Content");return a(),i("div",{class:T(["VPDoc",{"has-sidebar":l(n),"has-aside":l(o)}])},[u(p.$slots,"doc-top",{},void 0,!0),c("div",ws,[l(o)?(a(),i("div",{key:0,class:T(["aside",{"left-aside":l(r)}])},[Ls,c("div",Ss,[c("div",Ms,[h(Ft,null,{"aside-top":v(()=>[u(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),c("div",Ns,[c("div",Is,[u(p.$slots,"doc-before",{},void 0,!0),h(Ps),c("main",Ts,[h(g,{class:T(["vp-doc",[d.value,l(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),h(ps,null,{"doc-footer-before":v(()=>[u(p.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),u(p.$slots,"doc-after",{},void 0,!0)])])]),u(p.$slots,"doc-bottom",{},void 0,!0)],2)}}});const Bs=m(Cs,[["__scopeId","data-v-a3c25e27"]]),As=b({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{}},setup(s){const e=s,t=k(()=>e.href&&we.test(e.href)),n=k(()=>e.tag||e.href?"a":"button");return(o,r)=>(a(),$(F(n.value),{class:T(["VPButton",[o.size,o.theme]]),href:o.href?l(J)(o.href):void 0,target:t.value?"_blank":void 0,rel:t.value?"noreferrer":void 0},{default:v(()=>[x(L(o.text),1)]),_:1},8,["class","href","target","rel"]))}});const xs=m(As,[["__scopeId","data-v-1e76fe75"]]),Hs=["src","alt"],zs=b({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(s){return(e,t)=>{const n=j("VPImage",!0);return e.image?(a(),i(N,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),i("img",Z({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:l(ue)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Hs)):(a(),i(N,{key:1},[h(n,Z({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),h(n,Z({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}});const ee=m(zs,[["__scopeId","data-v-ab19afbb"]]),Ds=s=>(H("data-v-5a3e9999"),s=s(),z(),s),Es={class:"container"},Fs={class:"main"},Os={key:0,class:"name"},Gs=["innerHTML"],Us=["innerHTML"],js=["innerHTML"],Ks={key:0,class:"actions"},Rs={key:0,class:"image"},qs={class:"image-container"},Ws=Ds(()=>c("div",{class:"image-bg"},null,-1)),Ys=b({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(s){const e=ne("hero-image-slot-exists");return(t,n)=>(a(),i("div",{class:T(["VPHero",{"has-image":t.image||l(e)}])},[c("div",Es,[c("div",Fs,[u(t.$slots,"home-hero-info",{},()=>[t.name?(a(),i("h1",Os,[c("span",{innerHTML:t.name,class:"clip"},null,8,Gs)])):f("",!0),t.text?(a(),i("p",{key:1,innerHTML:t.text,class:"text"},null,8,Us)):f("",!0),t.tagline?(a(),i("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,js)):f("",!0)],!0),t.actions?(a(),i("div",Ks,[(a(!0),i(N,null,A(t.actions,o=>(a(),i("div",{key:o.link,class:"action"},[h(xs,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||l(e)?(a(),i("div",Rs,[c("div",qs,[Ws,u(t.$slots,"home-hero-image",{},()=>[t.image?(a(),$(ee,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}});const Js=m(Ys,[["__scopeId","data-v-5a3e9999"]]),Xs=b({__name:"VPHomeHero",setup(s){const{frontmatter:e}=P();return(t,n)=>l(e).hero?(a(),$(Js,{key:0,class:"VPHomeHero",name:l(e).hero.name,text:l(e).hero.text,tagline:l(e).hero.tagline,image:l(e).hero.image,actions:l(e).hero.actions},{"home-hero-info":v(()=>[u(t.$slots,"home-hero-info")]),"home-hero-image":v(()=>[u(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Zs={},Qs={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},en=c("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),tn=[en];function sn(s,e){return a(),i("svg",Qs,tn)}const nn=m(Zs,[["render",sn]]),on={class:"box"},an={key:0,class:"icon"},rn=["innerHTML"],ln=["innerHTML"],cn=["innerHTML"],un={key:4,class:"link-text"},dn={class:"link-text-value"},_n=b({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(s){return(e,t)=>(a(),$(E,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:v(()=>[c("article",on,[typeof e.icon=="object"&&e.icon.wrap?(a(),i("div",an,[h(ee,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),$(ee,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),i("div",{key:2,class:"icon",innerHTML:e.icon},null,8,rn)):f("",!0),c("h2",{class:"title",innerHTML:e.title},null,8,ln),e.details?(a(),i("p",{key:3,class:"details",innerHTML:e.details},null,8,cn)):f("",!0),e.linkText?(a(),i("div",un,[c("p",dn,[x(L(e.linkText)+" ",1),h(nn,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}});const vn=m(_n,[["__scopeId","data-v-ee984185"]]),pn={key:0,class:"VPFeatures"},hn={class:"container"},fn={class:"items"},mn=b({__name:"VPFeatures",props:{features:{}},setup(s){const e=s,t=k(()=>{const n=e.features.length;if(n){if(n===2)return"grid-2";if(n===3)return"grid-3";if(n%3===0)return"grid-6";if(n>3)return"grid-4"}else return});return(n,o)=>n.features?(a(),i("div",pn,[c("div",hn,[c("div",fn,[(a(!0),i(N,null,A(n.features,r=>(a(),i("div",{key:r.title,class:T(["item",[t.value]])},[h(vn,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}});const gn=m(mn,[["__scopeId","data-v-b1eea84a"]]),bn=b({__name:"VPHomeFeatures",setup(s){const{frontmatter:e}=P();return(t,n)=>l(e).features?(a(),$(gn,{key:0,class:"VPHomeFeatures",features:l(e).features},null,8,["features"])):f("",!0)}}),$n={class:"VPHome"},kn=b({__name:"VPHome",setup(s){return(e,t)=>{const n=j("Content");return a(),i("div",$n,[u(e.$slots,"home-hero-before",{},void 0,!0),h(Xs,null,{"home-hero-info":v(()=>[u(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),u(e.$slots,"home-hero-after",{},void 0,!0),u(e.$slots,"home-features-before",{},void 0,!0),h(bn),u(e.$slots,"home-features-after",{},void 0,!0),h(n)])}}});const yn=m(kn,[["__scopeId","data-v-20eabd3a"]]),Pn={},Vn={class:"VPPage"};function wn(s,e){const t=j("Content");return a(),i("div",Vn,[u(s.$slots,"page-top"),h(t),u(s.$slots,"page-bottom")])}const Ln=m(Pn,[["render",wn]]),Sn=b({__name:"VPContent",setup(s){const{page:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>(a(),i("div",{class:T(["VPContent",{"has-sidebar":l(n),"is-home":l(t).layout==="home"}]),id:"VPContent"},[l(e).isNotFound?u(o.$slots,"not-found",{key:0},()=>[h(pt)],!0):l(t).layout==="page"?(a(),$(Ln,{key:1},{"page-top":v(()=>[u(o.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(o.$slots,"page-bottom",{},void 0,!0)]),_:3})):l(t).layout==="home"?(a(),$(yn,{key:2},{"home-hero-before":v(()=>[u(o.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(o.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(o.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(o.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(o.$slots,"home-features-after",{},void 0,!0)]),_:3})):l(t).layout&&l(t).layout!=="doc"?(a(),$(F(l(t).layout),{key:3})):(a(),$(Bs,{key:4},{"doc-top":v(()=>[u(o.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(o.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[u(o.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(o.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(o.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[u(o.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[u(o.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(o.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(o.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(o.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[u(o.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const Mn=m(Sn,[["__scopeId","data-v-3cf691b6"]]),Nn={class:"container"},In=["innerHTML"],Tn=["innerHTML"],Cn=b({__name:"VPFooter",setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D();return(o,r)=>l(e).footer&&l(t).footer!==!1?(a(),i("footer",{key:0,class:T(["VPFooter",{"has-sidebar":l(n)}])},[c("div",Nn,[l(e).footer.message?(a(),i("p",{key:0,class:"message",innerHTML:l(e).footer.message},null,8,In)):f("",!0),l(e).footer.copyright?(a(),i("p",{key:1,class:"copyright",innerHTML:l(e).footer.copyright},null,8,Tn)):f("",!0)])],2)):f("",!0)}});const Bn=m(Cn,[["__scopeId","data-v-e4279f1c"]]),An={class:"header"},xn={class:"outline"},Hn=b({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(s){const e=s,{theme:t}=P(),n=M(!1),o=M(0),r=M();Y(()=>{n.value=!1});function d(){n.value=!n.value,o.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(g){g.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),Oe(()=>{n.value=!1}))}function _(){n.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(g,V)=>(a(),i("div",{class:"VPLocalNavOutlineDropdown",style:Fe({"--vp-vh":o.value+"px"})},[g.headers.length>0?(a(),i("button",{key:0,onClick:d,class:T({open:n.value})},[x(L(l(ve)(l(t)))+" ",1),h(fe,{class:"icon"})],2)):(a(),i("button",{key:1,onClick:_},L(l(t).returnToTopLabel||"Return to top"),1)),h(ce,{name:"flyout"},{default:v(()=>[n.value?(a(),i("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:p},[c("div",An,[c("a",{class:"top-link",href:"#",onClick:_},L(l(t).returnToTopLabel||"Return to top"),1)]),c("div",xn,[h(he,{headers:g.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}});const zn=m(Hn,[["__scopeId","data-v-24251f6f"]]),Dn={},En={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Fn=c("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),On=c("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),Gn=c("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Un=c("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),jn=[Fn,On,Gn,Un];function Kn(s,e){return a(),i("svg",En,jn)}const Rn=m(Dn,[["render",Kn]]),qn=["aria-expanded"],Wn={class:"menu-text"},Yn=b({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(s){const{theme:e,frontmatter:t}=P(),{hasSidebar:n}=D(),{y:o}=Le(),r=_e([]),d=M(0);G(()=>{d.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Y(()=>{r.value=pe(t.value.outline??e.value.outline)});const p=k(()=>r.value.length===0&&!n.value),_=k(()=>({VPLocalNav:!0,fixed:p.value,"reached-top":o.value>=d.value}));return(g,V)=>l(t).layout!=="home"&&(!p.value||l(o)>=d.value)?(a(),i("div",{key:0,class:T(_.value)},[l(n)?(a(),i("button",{key:0,class:"menu","aria-expanded":g.open,"aria-controls":"VPSidebarNav",onClick:V[0]||(V[0]=y=>g.$emit("open-menu"))},[h(Rn,{class:"menu-icon"}),c("span",Wn,L(l(e).sidebarMenuLabel||"Menu"),1)],8,qn)):f("",!0),h(zn,{headers:r.value,navHeight:d.value},null,8,["headers","navHeight"])],2)):f("",!0)}});const Jn=m(Yn,[["__scopeId","data-v-9e669cc1"]]);function Xn(){const s=M(!1);function e(){s.value=!0,window.addEventListener("resize",o)}function t(){s.value=!1,window.removeEventListener("resize",o)}function n(){s.value?t():e()}function o(){window.outerWidth>=768&&t()}const r=se();return U(()=>r.path,t),{isScreenOpen:s,openScreen:e,closeScreen:t,toggleScreen:n}}const Zn={},Qn={class:"VPSwitch",type:"button",role:"switch"},eo={class:"check"},to={key:0,class:"icon"};function so(s,e){return a(),i("button",Qn,[c("span",eo,[s.$slots.default?(a(),i("span",to,[u(s.$slots,"default",{},void 0,!0)])):f("",!0)])])}const no=m(Zn,[["render",so],["__scopeId","data-v-1c29e291"]]),oo={},ao={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ro=c("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),lo=[ro];function io(s,e){return a(),i("svg",ao,lo)}const co=m(oo,[["render",io]]),uo={},_o={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},vo=Ge('',9),po=[vo];function ho(s,e){return a(),i("svg",_o,po)}const fo=m(uo,[["render",ho]]),mo=b({__name:"VPSwitchAppearance",setup(s){const{isDark:e}=P(),t=ne("toggle-appearance",()=>{e.value=!e.value});return(n,o)=>(a(),$(no,{title:"toggle dark mode",class:"VPSwitchAppearance","aria-checked":l(e),onClick:l(t)},{default:v(()=>[h(fo,{class:"sun"}),h(co,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const me=m(mo,[["__scopeId","data-v-3329432d"]]),go={key:0,class:"VPNavBarAppearance"},bo=b({__name:"VPNavBarAppearance",setup(s){const{site:e}=P();return(t,n)=>l(e).appearance&&l(e).appearance!=="force-dark"?(a(),i("div",go,[h(me)])):f("",!0)}});const $o=m(bo,[["__scopeId","data-v-283b26e9"]]),ge=M();let Te=!1,ae=0;function ko(s){const e=M(!1);if(q){!Te&&yo(),ae++;const t=U(ge,n=>{var o,r,d;n===s.el.value||(o=s.el.value)!=null&&o.contains(n)?(e.value=!0,(r=s.onFocus)==null||r.call(s)):(e.value=!1,(d=s.onBlur)==null||d.call(s))});de(()=>{t(),ae--,ae||Po()})}return Ue(e)}function yo(){document.addEventListener("focusin",Ce),Te=!0,ge.value=document.activeElement}function Po(){document.removeEventListener("focusin",Ce)}function Ce(){ge.value=document.activeElement}const Vo={},wo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Lo=c("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),So=[Lo];function Mo(s,e){return a(),i("svg",wo,So)}const Be=m(Vo,[["render",Mo]]),No={},Io={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},To=c("circle",{cx:"12",cy:"12",r:"2"},null,-1),Co=c("circle",{cx:"19",cy:"12",r:"2"},null,-1),Bo=c("circle",{cx:"5",cy:"12",r:"2"},null,-1),Ao=[To,Co,Bo];function xo(s,e){return a(),i("svg",Io,Ao)}const Ho=m(No,[["render",xo]]),zo={class:"VPMenuLink"},Do=b({__name:"VPMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),i("div",zo,[h(E,{class:T({active:l(O)(l(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[x(L(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}});const oe=m(Do,[["__scopeId","data-v-f51f088d"]]),Eo={class:"VPMenuGroup"},Fo={key:0,class:"title"},Oo=b({__name:"VPMenuGroup",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),i("div",Eo,[e.text?(a(),i("p",Fo,L(e.text),1)):f("",!0),(a(!0),i(N,null,A(e.items,n=>(a(),i(N,null,["link"in n?(a(),$(oe,{key:0,item:n},null,8,["item"])):f("",!0)],64))),256))]))}});const Go=m(Oo,[["__scopeId","data-v-a6b0397c"]]),Uo={class:"VPMenu"},jo={key:0,class:"items"},Ko=b({__name:"VPMenu",props:{items:{}},setup(s){return(e,t)=>(a(),i("div",Uo,[e.items?(a(),i("div",jo,[(a(!0),i(N,null,A(e.items,n=>(a(),i(N,{key:n.text},["link"in n?(a(),$(oe,{key:0,item:n},null,8,["item"])):(a(),$(Go,{key:1,text:n.text,items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0),u(e.$slots,"default",{},void 0,!0)]))}});const Ro=m(Ko,[["__scopeId","data-v-e42ed9b3"]]),qo=["aria-expanded","aria-label"],Wo={key:0,class:"text"},Yo=["innerHTML"],Jo={class:"menu"},Xo=b({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(s){const e=M(!1),t=M();ko({el:t,onBlur:n});function n(){e.value=!1}return(o,r)=>(a(),i("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=d=>e.value=!0),onMouseleave:r[2]||(r[2]=d=>e.value=!1)},[c("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":o.label,onClick:r[0]||(r[0]=d=>e.value=!e.value)},[o.button||o.icon?(a(),i("span",Wo,[o.icon?(a(),$(F(o.icon),{key:0,class:"option-icon"})):f("",!0),o.button?(a(),i("span",{key:1,innerHTML:o.button},null,8,Yo)):f("",!0),h(Be,{class:"text-icon"})])):(a(),$(Ho,{key:1,class:"icon"}))],8,qo),c("div",Jo,[h(Ro,{items:o.items},{default:v(()=>[u(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const be=m(Xo,[["__scopeId","data-v-aa8de344"]]),Zo={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},Qo=["href","aria-label","innerHTML"],ea=b({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(s){const e=s,t=k(()=>typeof e.icon=="object"?e.icon.svg:Zo[e.icon]);return(n,o)=>(a(),i("a",{class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,Qo))}});const ta=m(ea,[["__scopeId","data-v-16cf740a"]]),sa={class:"VPSocialLinks"},na=b({__name:"VPSocialLinks",props:{links:{}},setup(s){return(e,t)=>(a(),i("div",sa,[(a(!0),i(N,null,A(e.links,({link:n,icon:o,ariaLabel:r})=>(a(),$(ta,{key:n,icon:o,link:n,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}});const $e=m(na,[["__scopeId","data-v-e71e869c"]]),oa={key:0,class:"group translations"},aa={class:"trans-title"},ra={key:1,class:"group"},la={class:"item appearance"},ia={class:"label"},ca={class:"appearance-action"},ua={key:2,class:"group"},da={class:"item social-links"},_a=b({__name:"VPNavBarExtra",setup(s){const{site:e,theme:t}=P(),{localeLinks:n,currentLang:o}=X({correspondingLink:!0}),r=k(()=>n.value.length&&o.value.label||e.value.appearance||t.value.socialLinks);return(d,p)=>r.value?(a(),$(be,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[l(n).length&&l(o).label?(a(),i("div",oa,[c("p",aa,L(l(o).label),1),(a(!0),i(N,null,A(l(n),_=>(a(),$(oe,{key:_.link,item:_},null,8,["item"]))),128))])):f("",!0),l(e).appearance?(a(),i("div",ra,[c("div",la,[c("p",ia,L(l(t).darkModeSwitchLabel||"Appearance"),1),c("div",ca,[h(me)])])])):f("",!0),l(t).socialLinks?(a(),i("div",ua,[c("div",da,[h($e,{class:"social-links-list",links:l(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}});const va=m(_a,[["__scopeId","data-v-c8c2ae4b"]]),pa=s=>(H("data-v-6bee1efd"),s=s(),z(),s),ha=["aria-expanded"],fa=pa(()=>c("span",{class:"container"},[c("span",{class:"top"}),c("span",{class:"middle"}),c("span",{class:"bottom"})],-1)),ma=[fa],ga=b({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(s){return(e,t)=>(a(),i("button",{type:"button",class:T(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=n=>e.$emit("click"))},ma,10,ha))}});const ba=m(ga,[["__scopeId","data-v-6bee1efd"]]),$a=["innerHTML"],ka=b({__name:"VPNavBarMenuLink",props:{item:{}},setup(s){const{page:e}=P();return(t,n)=>(a(),$(E,{class:T({VPNavBarMenuLink:!0,active:l(O)(l(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[c("span",{innerHTML:t.item.text},null,8,$a)]),_:1},8,["class","href","target","rel"]))}});const ya=m(ka,[["__scopeId","data-v-cb318fec"]]),Pa=b({__name:"VPNavBarMenuGroup",props:{item:{}},setup(s){const e=s,{page:t}=P(),n=r=>"link"in r?O(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(n),o=k(()=>n(e.item));return(r,d)=>(a(),$(be,{class:T({VPNavBarMenuGroup:!0,active:l(O)(l(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||o.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),Va=s=>(H("data-v-f732b5d0"),s=s(),z(),s),wa={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},La=Va(()=>c("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Sa=b({__name:"VPNavBarMenu",setup(s){const{theme:e}=P();return(t,n)=>l(e).nav?(a(),i("nav",wa,[La,(a(!0),i(N,null,A(l(e).nav,o=>(a(),i(N,{key:o.text},["link"in o?(a(),$(ya,{key:0,item:o},null,8,["item"])):(a(),$(Pa,{key:1,item:o},null,8,["item"]))],64))),128))])):f("",!0)}});const Ma=m(Sa,[["__scopeId","data-v-f732b5d0"]]);function Na(s,e){const{localeIndex:t}=P();function n(o){var S,C;const r=o.split("."),d=s&&typeof s=="object",p=d&&((C=(S=s.locales)==null?void 0:S[t.value])==null?void 0:C.translations)||null,_=d&&s.translations||null;let g=p,V=_,y=e;const I=r.pop();for(const B of r){let w=null;const K=y==null?void 0:y[B];K&&(w=y=K);const W=V==null?void 0:V[B];W&&(w=V=W);const R=g==null?void 0:g[B];R&&(w=g=R),K||(y=w),W||(V=w),R||(g=w)}return(g==null?void 0:g[I])??(V==null?void 0:V[I])??(y==null?void 0:y[I])??""}return n}const Ia=["aria-label"],Ta={class:"DocSearch-Button-Container"},Ca=c("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[c("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ba={class:"DocSearch-Button-Placeholder"},Aa=c("span",{class:"DocSearch-Button-Keys"},[c("kbd",{class:"DocSearch-Button-Key"}),c("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Pe=b({__name:"VPNavBarSearchButton",setup(s){const{theme:e}=P(),t={button:{buttonText:"Search",buttonAriaLabel:"Search"}},n=je(Na)(Ke(()=>{var o;return(o=e.value.search)==null?void 0:o.options}),t);return(o,r)=>(a(),i("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":l(n)("button.buttonAriaLabel")},[c("span",Ta,[Ca,c("span",Ba,L(l(n)("button.buttonText")),1)]),Aa],8,Ia))}});const xa={class:"VPNavBarSearch"},Ha={id:"local-search"},za={key:1,id:"docsearch"},Da=b({__name:"VPNavBarSearch",setup(s){const e=Re(()=>qe(()=>import("./VPLocalSearchBox.004b014b.js"),["assets/chunks/VPLocalSearchBox.004b014b.js","assets/chunks/framework.0e8ae64e.js"])),t=()=>null,{theme:n}=P(),o=M(!1),r=M(!1);G(()=>{});function d(){o.value||(o.value=!0,setTimeout(p,16))}function p(){const y=new Event("keydown");y.key="k",y.metaKey=!0,window.dispatchEvent(y),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||p()},16)}function _(y){const I=y.target,S=I.tagName;return I.isContentEditable||S==="INPUT"||S==="SELECT"||S==="TEXTAREA"}const g=M(!1);ke("k",y=>{(y.ctrlKey||y.metaKey)&&(y.preventDefault(),g.value=!0)}),ke("/",y=>{_(y)||(y.preventDefault(),g.value=!0)});const V="local";return(y,I)=>{var S;return a(),i("div",xa,[l(V)==="local"?(a(),i(N,{key:0},[g.value?(a(),$(l(e),{key:0,onClose:I[0]||(I[0]=C=>g.value=!1)})):f("",!0),c("div",Ha,[h(Pe,{onClick:I[1]||(I[1]=C=>g.value=!0)})])],64)):l(V)==="algolia"?(a(),i(N,{key:1},[o.value?(a(),$(l(t),{key:0,algolia:((S=l(n).search)==null?void 0:S.options)??l(n).algolia,onVnodeBeforeMount:I[2]||(I[2]=C=>r.value=!0)},null,8,["algolia"])):f("",!0),r.value?f("",!0):(a(),i("div",za,[h(Pe,{onClick:d})]))],64)):f("",!0)])}}});const Ea=b({__name:"VPNavBarSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>l(e).socialLinks?(a(),$($e,{key:0,class:"VPNavBarSocialLinks",links:l(e).socialLinks},null,8,["links"])):f("",!0)}});const Fa=m(Ea,[["__scopeId","data-v-ef6192dc"]]),Oa=["href"],Ga=b({__name:"VPNavBarTitle",setup(s){const{site:e,theme:t}=P(),{hasSidebar:n}=D(),{currentLang:o}=X();return(r,d)=>(a(),i("div",{class:T(["VPNavBarTitle",{"has-sidebar":l(n)}])},[c("a",{class:"title",href:l(t).logoLink??l(J)(l(o).link)},[u(r.$slots,"nav-bar-title-before",{},void 0,!0),l(t).logo?(a(),$(ee,{key:0,class:"logo",image:l(t).logo},null,8,["image"])):f("",!0),l(t).siteTitle?(a(),i(N,{key:1},[x(L(l(t).siteTitle),1)],64)):l(t).siteTitle===void 0?(a(),i(N,{key:2},[x(L(l(e).title),1)],64)):f("",!0),u(r.$slots,"nav-bar-title-after",{},void 0,!0)],8,Oa)],2))}});const Ua=m(Ga,[["__scopeId","data-v-2973dbb4"]]),ja={},Ka={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ra=c("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),qa=c("path",{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 ",class:"css-c4d79v"},null,-1),Wa=[Ra,qa];function Ya(s,e){return a(),i("svg",Ka,Wa)}const Ae=m(ja,[["render",Ya]]),Ja={class:"items"},Xa={class:"title"},Za=b({__name:"VPNavBarTranslations",setup(s){const{theme:e}=P(),{localeLinks:t,currentLang:n}=X({correspondingLink:!0});return(o,r)=>l(t).length&&l(n).label?(a(),$(be,{key:0,class:"VPNavBarTranslations",icon:Ae,label:l(e).langMenuLabel||"Change language"},{default:v(()=>[c("div",Ja,[c("p",Xa,L(l(n).label),1),(a(!0),i(N,null,A(l(t),d=>(a(),$(oe,{key:d.link,item:d},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}});const Qa=m(Za,[["__scopeId","data-v-ff4524ae"]]),er=s=>(H("data-v-f1abbc6e"),s=s(),z(),s),tr={class:"container"},sr={class:"title"},nr={class:"content"},or=er(()=>c("div",{class:"curtain"},null,-1)),ar={class:"content-body"},rr=b({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(s){const{y:e}=Le(),{hasSidebar:t}=D(),{frontmatter:n}=P(),o=M({});return Ve(()=>{o.value={"has-sidebar":t.value,top:n.value.layout==="home"&&e.value===0}}),(r,d)=>(a(),i("div",{class:T(["VPNavBar",o.value])},[c("div",tr,[c("div",sr,[h(Ua,null,{"nav-bar-title-before":v(()=>[u(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(r.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),c("div",nr,[or,c("div",ar,[u(r.$slots,"nav-bar-content-before",{},void 0,!0),h(Da,{class:"search"}),h(Ma,{class:"menu"}),h(Qa,{class:"translations"}),h($o,{class:"appearance"}),h(Fa,{class:"social-links"}),h(va,{class:"extra"}),u(r.$slots,"nav-bar-content-after",{},void 0,!0),h(ba,{class:"hamburger",active:r.isScreenOpen,onClick:d[0]||(d[0]=p=>r.$emit("toggle-screen"))},null,8,["active"])])])])],2))}});const lr=m(rr,[["__scopeId","data-v-f1abbc6e"]]),ir={key:0,class:"VPNavScreenAppearance"},cr={class:"text"},ur=b({__name:"VPNavScreenAppearance",setup(s){const{site:e,theme:t}=P();return(n,o)=>l(e).appearance?(a(),i("div",ir,[c("p",cr,L(l(t).darkModeSwitchLabel||"Appearance"),1),h(me)])):f("",!0)}});const dr=m(ur,[["__scopeId","data-v-0dc5cf49"]]),_r=b({__name:"VPNavScreenMenuLink",props:{item:{}},setup(s){const e=ne("close-screen");return(t,n)=>(a(),$(E,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:l(e)},{default:v(()=>[x(L(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const vr=m(_r,[["__scopeId","data-v-fe523e3d"]]),pr={},hr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},fr=c("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),mr=[fr];function gr(s,e){return a(),i("svg",hr,mr)}const br=m(pr,[["render",gr]]),$r=b({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(s){const e=ne("close-screen");return(t,n)=>(a(),$(E,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:l(e)},{default:v(()=>[x(L(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const xe=m($r,[["__scopeId","data-v-aea78dd1"]]),kr={class:"VPNavScreenMenuGroupSection"},yr={key:0,class:"title"},Pr=b({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),i("div",kr,[e.text?(a(),i("p",yr,L(e.text),1)):f("",!0),(a(!0),i(N,null,A(e.items,n=>(a(),$(xe,{key:n.text,item:n},null,8,["item"]))),128))]))}});const Vr=m(Pr,[["__scopeId","data-v-f60dbfa7"]]),wr=["aria-controls","aria-expanded"],Lr={class:"button-text"},Sr=["id"],Mr={key:1,class:"group"},Nr=b({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(s){const e=s,t=M(!1),n=k(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function o(){t.value=!t.value}return(r,d)=>(a(),i("div",{class:T(["VPNavScreenMenuGroup",{open:t.value}])},[c("button",{class:"button","aria-controls":n.value,"aria-expanded":t.value,onClick:o},[c("span",Lr,L(r.text),1),h(br,{class:"button-icon"})],8,wr),c("div",{id:n.value,class:"items"},[(a(!0),i(N,null,A(r.items,p=>(a(),i(N,{key:p.text},["link"in p?(a(),i("div",{key:p.text,class:"item"},[h(xe,{item:p},null,8,["item"])])):(a(),i("div",Mr,[h(Vr,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,Sr)],2))}});const Ir=m(Nr,[["__scopeId","data-v-c2c554ed"]]),Tr={key:0,class:"VPNavScreenMenu"},Cr=b({__name:"VPNavScreenMenu",setup(s){const{theme:e}=P();return(t,n)=>l(e).nav?(a(),i("nav",Tr,[(a(!0),i(N,null,A(l(e).nav,o=>(a(),i(N,{key:o.text},["link"in o?(a(),$(vr,{key:0,item:o},null,8,["item"])):(a(),$(Ir,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Br=b({__name:"VPNavScreenSocialLinks",setup(s){const{theme:e}=P();return(t,n)=>l(e).socialLinks?(a(),$($e,{key:0,class:"VPNavScreenSocialLinks",links:l(e).socialLinks},null,8,["links"])):f("",!0)}}),Ar={class:"list"},xr=b({__name:"VPNavScreenTranslations",setup(s){const{localeLinks:e,currentLang:t}=X({correspondingLink:!0}),n=M(!1);function o(){n.value=!n.value}return(r,d)=>l(e).length&&l(t).label?(a(),i("div",{key:0,class:T(["VPNavScreenTranslations",{open:n.value}])},[c("button",{class:"title",onClick:o},[h(Ae,{class:"icon lang"}),x(" "+L(l(t).label)+" ",1),h(Be,{class:"icon chevron"})]),c("ul",Ar,[(a(!0),i(N,null,A(l(e),p=>(a(),i("li",{key:p.link,class:"item"},[h(E,{class:"link",href:p.link},{default:v(()=>[x(L(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}});const Hr=m(xr,[["__scopeId","data-v-41505286"]]),zr={class:"container"},Dr=b({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(s){const e=M(null),t=Se(q?document.body:null);return(n,o)=>(a(),$(ce,{name:"fade",onEnter:o[0]||(o[0]=r=>t.value=!0),onAfterLeave:o[1]||(o[1]=r=>t.value=!1)},{default:v(()=>[n.open?(a(),i("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[c("div",zr,[u(n.$slots,"nav-screen-content-before",{},void 0,!0),h(Cr,{class:"menu"}),h(Hr,{class:"translations"}),h(dr,{class:"appearance"}),h(Br,{class:"social-links"}),u(n.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}});const Er=m(Dr,[["__scopeId","data-v-57cce842"]]),Fr={key:0,class:"VPNav"},Or=b({__name:"VPNav",setup(s){const{isScreenOpen:e,closeScreen:t,toggleScreen:n}=Xn(),{frontmatter:o}=P(),r=k(()=>o.value.navbar!==!1);return Me("close-screen",t),te(()=>{q&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(d,p)=>r.value?(a(),i("header",Fr,[h(lr,{"is-screen-open":l(e),onToggleScreen:l(n)},{"nav-bar-title-before":v(()=>[u(d.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(d.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(d.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(d.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),h(Er,{open:l(e)},{"nav-screen-content-before":v(()=>[u(d.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(d.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}});const Gr=m(Or,[["__scopeId","data-v-7ad780c2"]]),Ur=s=>(H("data-v-bd01e0d5"),s=s(),z(),s),jr=["role","tabindex"],Kr=Ur(()=>c("div",{class:"indicator"},null,-1)),Rr=["onKeydown"],qr={key:1,class:"items"},Wr=b({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(s){const e=s,{collapsed:t,collapsible:n,isLink:o,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}=gt(k(()=>e.item)),g=k(()=>p.value?"section":"div"),V=k(()=>o.value?"a":"div"),y=k(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),I=k(()=>o.value?void 0:"button"),S=k(()=>[[`level-${e.depth}`],{collapsible:n.value},{collapsed:t.value},{"is-link":o.value},{"is-active":r.value},{"has-active":d.value}]);function C(w){"key"in w&&w.key!=="Enter"||!e.item.link&&_()}function B(){e.item.link&&_()}return(w,K)=>{const W=j("VPSidebarItem",!0);return a(),$(F(g.value),{class:T(["VPSidebarItem",S.value])},{default:v(()=>[w.item.text?(a(),i("div",Z({key:0,class:"item",role:I.value},Ye(w.item.items?{click:C,keydown:C}:{},!0),{tabindex:w.item.items&&0}),[Kr,w.item.link?(a(),$(E,{key:0,tag:V.value,class:"link",href:w.item.link,rel:w.item.rel,target:w.item.target},{default:v(()=>[(a(),$(F(y.value),{class:"text",innerHTML:w.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),$(F(y.value),{key:1,class:"text",innerHTML:w.item.text},null,8,["innerHTML"])),w.item.collapsed!=null?(a(),i("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:B,onKeydown:We(B,["enter"]),tabindex:"0"},[h(fe,{class:"caret-icon"})],40,Rr)):f("",!0)],16,jr)):f("",!0),w.item.items&&w.item.items.length?(a(),i("div",qr,[w.depth<5?(a(!0),i(N,{key:0},A(w.item.items,R=>(a(),$(W,{key:R.text,item:R,depth:w.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}});const Yr=m(Wr,[["__scopeId","data-v-bd01e0d5"]]),He=s=>(H("data-v-ee2efba5"),s=s(),z(),s),Jr=He(()=>c("div",{class:"curtain"},null,-1)),Xr={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Zr=He(()=>c("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Qr=b({__name:"VPSidebar",props:{open:{type:Boolean}},setup(s){const{sidebarGroups:e,hasSidebar:t}=D(),n=s,o=M(null),r=Se(q?document.body:null);return U([n,o],()=>{var d;n.open?(r.value=!0,(d=o.value)==null||d.focus()):r.value=!1},{immediate:!0,flush:"post"}),(d,p)=>l(t)?(a(),i("aside",{key:0,class:T(["VPSidebar",{open:d.open}]),ref_key:"navEl",ref:o,onClick:p[0]||(p[0]=Je(()=>{},["stop"]))},[Jr,c("nav",Xr,[Zr,u(d.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),i(N,null,A(l(e),_=>(a(),i("div",{key:_.text,class:"group"},[h(Yr,{item:_,depth:0},null,8,["item"])]))),128)),u(d.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}});const el=m(Qr,[["__scopeId","data-v-ee2efba5"]]),tl=b({__name:"VPSkipLink",setup(s){const e=se(),t=M();U(()=>e.path,()=>t.value.focus());function n({target:o}){const r=document.getElementById(decodeURIComponent(o.hash).slice(1));if(r){const d=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",d)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",d),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(a(),i(N,null,[c("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),c("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:n}," Skip to content ")],64))}});const sl=m(tl,[["__scopeId","data-v-c8291ffa"]]),nl=b({__name:"Layout",setup(s){const{isOpen:e,open:t,close:n}=D(),o=se();U(()=>o.path,n),mt(e,n);const{frontmatter:r}=P(),d=Xe(),p=k(()=>!!d["home-hero-image"]);return Me("hero-image-slot-exists",p),(_,g)=>{const V=j("Content");return l(r).layout!==!1?(a(),i("div",{key:0,class:T(["Layout",l(r).pageClass])},[u(_.$slots,"layout-top",{},void 0,!0),h(sl),h(st,{class:"backdrop",show:l(e),onClick:l(n)},null,8,["show","onClick"]),h(Gr,null,{"nav-bar-title-before":v(()=>[u(_.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[u(_.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[u(_.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[u(_.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[u(_.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[u(_.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),h(Jn,{open:l(e),onOpenMenu:l(t)},null,8,["open","onOpenMenu"]),h(el,{open:l(e)},{"sidebar-nav-before":v(()=>[u(_.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[u(_.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),h(Mn,null,{"page-top":v(()=>[u(_.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[u(_.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[u(_.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[u(_.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[u(_.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[u(_.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[u(_.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[u(_.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[u(_.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[u(_.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[u(_.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[u(_.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[u(_.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[u(_.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[u(_.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[u(_.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[u(_.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[u(_.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[u(_.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[u(_.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),h(Bn),u(_.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),$(V,{key:1}))}}});const ol=m(nl,[["__scopeId","data-v-9d8abc1e"]]);const rl={Layout:ol,enhanceApp:({app:s})=>{s.component("Badge",Qe)}};export{Na as c,rl as t,P as u}; diff --git a/assets/counter_index.md.6e6af5ae.js b/assets/counter_index.md.6e6af5ae.js new file mode 100644 index 00000000..3a0b7fc7 --- /dev/null +++ b/assets/counter_index.md.6e6af5ae.js @@ -0,0 +1,88 @@ +import{_ as s,o as n,c as a,Q as o}from"./chunks/framework.0e8ae64e.js";const u=JSON.parse('{"title":"Counter","description":"","frontmatter":{},"headers":[],"relativePath":"counter/index.md","filePath":"counter/index.md"}'),e={name:"counter/index.md"},l=o(`

Counter

We’re going build the classic frontend starter app, the counter, using ReasonReact. If you’ve already installed the starter project, you can run the project now:

  1. Go to the root directory of your melange-for-react-devs-template project
  2. Run make watch to start the Melange compiler in watch mode.
  3. In another terminal window, start the webpack dev server by running make serve. As a side effect, it will open a browser tab pointed to http://localhost:8080/.

Open Index.re and you’ll see this:

re
module App = {
+  [@react.component]
+  let make = () => <div> {React.string("welcome to my app")} </div>;
+};
module App = {
+  [@react.component]
+  let make = () => <div> {React.string("welcome to my app")} </div>;
+};

This is just about the simplest component you can make, but through it, we can start to see some of the key differences of developing with ReasonReact:

  • All components must be inside a module
  • The make function renders the component and returns React.element
  • We must decorate the make function with [@react.component]
  • In JSX, we must wrap strings with calls to React.string

Let’s go over these differences in more detail.

Components are modules

In the example above, a new module named App is defined. OCaml’s modules are somewhat like JavaScript modules, with one notable difference being that there can be multiples modules inside a single file. For now, you just need to know that all components in ReasonReact are modules, and the name of the component comes from the name of the module.

The make function

The make function has the type unit => React.element, meaning it takes () as the only argument and returns an object of type React.element. You’ll need to decorate make with the attribute@react.component. We’ll go into the details later, but for now let’s just say that @react.component is there to reduce boilerplate and make our code more readable and easier to maintain.

Wrap strings with React.string

Unlike in normal React, we must wrap strings inside function calls to convert them to the React.element type. This is exactly what the React.string function does—if you hover over it, you’ll see that it displays the type string => React.element.

Using the App component

A little bit further down, we make use of the App component:

re
let node = ReactDOM.querySelector("#root");
+switch (node) {
+| Some(root) => ReactDOM.render(<App />, root)
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+};
let node = ReactDOM.querySelector("#root");
+switch (node) {
+| Some(root) => ReactDOM.render(<App />, root)
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+};

React.querySelector("#root") returns an option(Dom.element), meaning that if it doesn’t find the element, it returns None, and if it does find the element, it returns Some(Dom.element), i.e. the element wrapped in the Some constructor. The switch expression[1] allows you to succinctly express:

  • If node is Some(Dom.element), render the App component to the DOM
  • Otherwise if node is None, log an error message

We’ll talk more about option in the Celsius converter chapter.

The Counter component

Let’s create a counter component by creating a new file Counter.re with the following contents:

re
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0);
+
+  <div>
+    <button onClick={_evt => setCounter(v => v - 1)}>
+      {React.string("-")}
+    </button>
+    {React.string(Int.to_string(counter))}
+    <button onClick={_evt => setCounter(v => v + 1)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0);
+
+  <div>
+    <button onClick={_evt => setCounter(v => v - 1)}>
+      {React.string("-")}
+    </button>
+    {React.string(Int.to_string(counter))}
+    <button onClick={_evt => setCounter(v => v + 1)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};

This is a component with a single useState hook. It should look fairly familiar if you know about hooks in React. Note that we didn’t need to manually define a module for Counter, because all source files in OCaml are automatically modules, with the name of the module being the same as the name of the file.

Now let’s modify App so that it uses our new Counter component:

re
module App = {
+  [@react.component]
+  let make = () => <Counter />;
+};
module App = {
+  [@react.component]
+  let make = () => <Counter />;
+};

The pipe last operator

To display the number of the counter, we wrote {React.string(Int.to_string(counter))}, which converts an integer to a string, and then converts that string to React.element. In OCaml, there’s a way to apply a sequence of operations over some data so that it can be read from left to right:

reason
{counter |> Int.to_string |> React.string}
{counter |> Int.to_string |> React.string}

This uses the pipe last operator, which is useful for chaining function calls.

Basic styling

Let’s add a bit of styling to the root element of Counter:

re
<div
+  style={ReactDOMStyle.make(
+    ~padding="1em",
+    ~display="flex",
+    ~gridGap="1em",
+    (),
+  )}>
+  <button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span> {counter |> Int.to_string |> React.string} </span>
+  <button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;
<div
+  style={ReactDOMStyle.make(
+    ~padding="1em",
+    ~display="flex",
+    ~gridGap="1em",
+    (),
+  )}>
+  <button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span> {counter |> Int.to_string |> React.string} </span>
+  <button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;

Unlike in React, the style prop in ReasonReact doesn’t take a generic object, instead it takes an object of type ReactDOMStyle.t that is created by calling ReactDOMStyle.make. This isn’t a sustainable way to style our app—in the orders chapter, we’ll see how to style using CSS classes.

Congratulations! You’ve created your first ReasonReact app and component. In future chapters we’ll create more complex and interesting components.

Exercises

1. There aren’t any runtime errors in our app right now. But what happens if you try to remove the | None branch of the switch (node) expression?

2. What happens if you rename the _evt variable inside the button callback to evt?

3. Comment out the [@react.component] attribute in Counter.re. What happens?

Overview

What we covered in this section:

  • How to create and run a basic ReasonReact app
  • ReasonReact components are also modules
  • OCaml has an option type whose value can be either None or Some(_)
  • The pipe last operator is an alternate way to invoke functions that enables easy chaining of function calls
  • The style prop doesn’t take generic objects

Solutions

1. Removing the | None branch will result in a compilation error:

Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None
Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None

Basically, the compiler is telling you to handle the None case if you want to ship your app. This is part of what makes OCaml such a type-safe language.

2. Renaming _evt to evt results in a compilation error:

Error (warning 27 [unused-var-strict]): unused variable evt.
Error (warning 27 [unused-var-strict]): unused variable evt.

OCaml wants you to use all the variables you declare, unless they begin with _ (underscore).

3. Commenting out [@react.component] in Counter.re will trigger a compilation error in Index.re, at the place where Counter component is used:

File "Index.re", line 3, characters 19-27:
+3 |   let make = () => <Counter />;
+                       ^^^^^^^^^^^
+Error: Unbound value Counter.makeProps
File "Index.re", line 3, characters 19-27:
+3 |   let make = () => <Counter />;
+                       ^^^^^^^^^^^
+Error: Unbound value Counter.makeProps

For now, don’t worry about what Counter.makeProps is or where it came from—just remember that you need to put the [@react.component] attribute above your make function if you want your component to be usable in JSX. This is a very common newbie mistake. See the PPX chapter for more details.


Source code for this chapter can be found in the Melange for React Developers repo.


  1. Despite the name, don’t confuse OCaml’s switch expressions with JavaScript’s switch statements. ↩︎

`,56),p=[l];function t(c,r,i,y,E,d){return n(),a("div",null,p)}const g=s(e,[["render",t]]);export{u as __pageData,g as default}; diff --git a/assets/counter_index.md.6e6af5ae.lean.js b/assets/counter_index.md.6e6af5ae.lean.js new file mode 100644 index 00000000..9d1999a7 --- /dev/null +++ b/assets/counter_index.md.6e6af5ae.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,Q as o}from"./chunks/framework.0e8ae64e.js";const u=JSON.parse('{"title":"Counter","description":"","frontmatter":{},"headers":[],"relativePath":"counter/index.md","filePath":"counter/index.md"}'),e={name:"counter/index.md"},l=o("",56),p=[l];function t(c,r,i,y,E,d){return n(),a("div",null,p)}const g=s(e,[["render",t]]);export{u as __pageData,g as default}; diff --git a/assets/index.md.a20614f4.js b/assets/index.md.a20614f4.js new file mode 100644 index 00000000..75b769e3 --- /dev/null +++ b/assets/index.md.a20614f4.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as a}from"./chunks/framework.0e8ae64e.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Melange for React Devs","text":"A project-based, guided introduction to Melange, for React developers","actions":[{"theme":"brand","text":"Get started","link":"/intro/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/melange-re/melange-for-react-devs"}]}},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),n={name:"index.md"};function o(r,i,s,c,d,l){return t(),a("div")}const f=e(n,[["render",o]]);export{p as __pageData,f as default}; diff --git a/assets/index.md.a20614f4.lean.js b/assets/index.md.a20614f4.lean.js new file mode 100644 index 00000000..75b769e3 --- /dev/null +++ b/assets/index.md.a20614f4.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as a}from"./chunks/framework.0e8ae64e.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Melange for React Devs","text":"A project-based, guided introduction to Melange, for React developers","actions":[{"theme":"brand","text":"Get started","link":"/intro/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/melange-re/melange-for-react-devs"}]}},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),n={name:"index.md"};function o(r,i,s,c,d,l){return t(),a("div")}const f=e(n,[["render",o]]);export{p as __pageData,f as default}; diff --git a/assets/installation_index.md.a1fbd0b6.js b/assets/installation_index.md.a1fbd0b6.js new file mode 100644 index 00000000..2bbfda35 --- /dev/null +++ b/assets/installation_index.md.a1fbd0b6.js @@ -0,0 +1,20 @@ +import{_ as a,o as s,c as e,Q as n}from"./chunks/framework.0e8ae64e.js";const m=JSON.parse('{"title":"Installation","description":"","frontmatter":{},"headers":[],"relativePath":"installation/index.md","filePath":"installation/index.md"}'),o={name:"installation/index.md"},l=n(`

Installation

Prerequisites

Opam

We need opam, the OCaml Package Manager. There are many ways to install it depending on your platform, but let’s go with the simplest method:

bash
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
+opam init
+eval $(opam env)
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
+opam init
+eval $(opam env)

While opam init is running, it will prompt you with something like

Do you want opam to modify ~/.profile?
Do you want opam to modify ~/.profile?

Type y to agree.

After the installation completes, run

opam --version
opam --version

to verify that it succeeded.

Download and run the starter project

Let’s make sure that everything works by downloading and running our project template melange-for-react-devs-template.

bash
git clone https://github.com/melange-re/melange-for-react-devs-template
+cd melange-for-react-devs-template
+make init
+make build
+make serve
git clone https://github.com/melange-re/melange-for-react-devs-template
+cd melange-for-react-devs-template
+make init
+make build
+make serve

While make init is running, consider grabbing some coffee or other beverage, as it might take a while to fetch all the dependencies and build them. The last command, make serve, should open a tab in your default browser which points to http://localhost:8080/ and shows you a typical “Hello World” page. If you see this page, then the project was successfully installed!

Visual Studio Code Extension

  1. Open the Extensions tab in Visual Studio Code and search for “ocaml”.
  2. Install the OCaml Platform extension from OCaml Labs.
  3. To verify that the extension worked, open the melange-for-react-devs project in Visual Studio Code. OCaml code should be syntax highlighted, and you should see type annotations when you hover over variables.
  4. To enable auto-formatting, open your User Settings JSON file and add this snippet:
json
"[reason]": {
+  "editor.formatOnSave": true,
+  "editor.defaultFormatter": "ocamllabs.ocaml-platform"
+}
"[reason]": {
+  "editor.formatOnSave": true,
+  "editor.defaultFormatter": "ocamllabs.ocaml-platform"
+}
`,19),t=[l];function p(r,i,c,d,h,u){return s(),e("div",null,t)}const g=a(o,[["render",p]]);export{m as __pageData,g as default}; diff --git a/assets/installation_index.md.a1fbd0b6.lean.js b/assets/installation_index.md.a1fbd0b6.lean.js new file mode 100644 index 00000000..0f296dad --- /dev/null +++ b/assets/installation_index.md.a1fbd0b6.lean.js @@ -0,0 +1 @@ +import{_ as a,o as s,c as e,Q as n}from"./chunks/framework.0e8ae64e.js";const m=JSON.parse('{"title":"Installation","description":"","frontmatter":{},"headers":[],"relativePath":"installation/index.md","filePath":"installation/index.md"}'),o={name:"installation/index.md"},l=n("",19),t=[l];function p(r,i,c,d,h,u){return s(),e("div",null,t)}const g=a(o,[["render",p]]);export{m as __pageData,g as default}; diff --git a/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 b/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 new file mode 100644 index 00000000..2a687296 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 differ diff --git a/assets/inter-italic-cyrillic.ea42a392.woff2 b/assets/inter-italic-cyrillic.ea42a392.woff2 new file mode 100644 index 00000000..f6403515 Binary files /dev/null and b/assets/inter-italic-cyrillic.ea42a392.woff2 differ diff --git a/assets/inter-italic-greek-ext.4fbe9427.woff2 b/assets/inter-italic-greek-ext.4fbe9427.woff2 new file mode 100644 index 00000000..00218960 Binary files /dev/null and b/assets/inter-italic-greek-ext.4fbe9427.woff2 differ diff --git a/assets/inter-italic-greek.8f4463c4.woff2 b/assets/inter-italic-greek.8f4463c4.woff2 new file mode 100644 index 00000000..71c265f8 Binary files /dev/null and b/assets/inter-italic-greek.8f4463c4.woff2 differ diff --git a/assets/inter-italic-latin-ext.bd8920cc.woff2 b/assets/inter-italic-latin-ext.bd8920cc.woff2 new file mode 100644 index 00000000..9c1b9440 Binary files /dev/null and b/assets/inter-italic-latin-ext.bd8920cc.woff2 differ diff --git a/assets/inter-italic-latin.bd3b6f56.woff2 b/assets/inter-italic-latin.bd3b6f56.woff2 new file mode 100644 index 00000000..01fcf207 Binary files /dev/null and b/assets/inter-italic-latin.bd3b6f56.woff2 differ diff --git a/assets/inter-italic-vietnamese.6ce511fb.woff2 b/assets/inter-italic-vietnamese.6ce511fb.woff2 new file mode 100644 index 00000000..e4f788ee Binary files /dev/null and b/assets/inter-italic-vietnamese.6ce511fb.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.e75737ce.woff2 b/assets/inter-roman-cyrillic-ext.e75737ce.woff2 new file mode 100644 index 00000000..28593ccb Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.e75737ce.woff2 differ diff --git a/assets/inter-roman-cyrillic.5f2c6c8c.woff2 b/assets/inter-roman-cyrillic.5f2c6c8c.woff2 new file mode 100644 index 00000000..a20adc16 Binary files /dev/null and b/assets/inter-roman-cyrillic.5f2c6c8c.woff2 differ diff --git a/assets/inter-roman-greek-ext.ab0619bc.woff2 b/assets/inter-roman-greek-ext.ab0619bc.woff2 new file mode 100644 index 00000000..e3b0be76 Binary files /dev/null and b/assets/inter-roman-greek-ext.ab0619bc.woff2 differ diff --git a/assets/inter-roman-greek.d5a6d92a.woff2 b/assets/inter-roman-greek.d5a6d92a.woff2 new file mode 100644 index 00000000..f790e047 Binary files /dev/null and b/assets/inter-roman-greek.d5a6d92a.woff2 differ diff --git a/assets/inter-roman-latin-ext.0030eebd.woff2 b/assets/inter-roman-latin-ext.0030eebd.woff2 new file mode 100644 index 00000000..715bd903 Binary files /dev/null and b/assets/inter-roman-latin-ext.0030eebd.woff2 differ diff --git a/assets/inter-roman-latin.2ed14f66.woff2 b/assets/inter-roman-latin.2ed14f66.woff2 new file mode 100644 index 00000000..a540b7af Binary files /dev/null and b/assets/inter-roman-latin.2ed14f66.woff2 differ diff --git a/assets/inter-roman-vietnamese.14ce25a6.woff2 b/assets/inter-roman-vietnamese.14ce25a6.woff2 new file mode 100644 index 00000000..5a9f9cb9 Binary files /dev/null and b/assets/inter-roman-vietnamese.14ce25a6.woff2 differ diff --git a/assets/intro-to-dune_index.md.a5b8b6ca.js b/assets/intro-to-dune_index.md.a5b8b6ca.js new file mode 100644 index 00000000..8df09d8f --- /dev/null +++ b/assets/intro-to-dune_index.md.a5b8b6ca.js @@ -0,0 +1,154 @@ +import{_ as e,o as s,c as a,Q as n}from"./chunks/framework.0e8ae64e.js";const E=JSON.parse('{"title":"Introduction to Dune","description":"","frontmatter":{},"headers":[],"relativePath":"intro-to-dune/index.md","filePath":"intro-to-dune/index.md"}'),o={name:"intro-to-dune/index.md"},l=n(`

Introduction to Dune

Depending on how you’ve been following along, you may have several components in your project. Since these components don’t have much in common with each other, it makes sense to put them in separate, independent apps. To do that, we’ll have to spend a little time with Dune. Dune is a build system designed for OCaml projects, and it has many useful features. For our purposes, the feature of primary interest is its built-in support for Melange.

dune-project file

The dune-project file specifies metadata for a project, and should appear in the root directory of your project. If you’ve been using the starter project, then you’ve been using Dune this whole time and therefore already have a dune-project file:

clj
(lang dune 3.8)
+
+; Use version 0.1 of the melange plugin for dune
+
+(using melange 0.1)
+
+; Set the name which is used by error messages
+
+(name melange-for-react-devs)
(lang dune 3.8)
+
+; Use version 0.1 of the melange plugin for dune
+
+(using melange 0.1)
+
+; Set the name which is used by error messages
+
+(name melange-for-react-devs)

The line

clj
(using melange 0.1)
(using melange 0.1)

is necessary because we have to manually enable the Melange extension for Dune in order to use it. Note that the version of the Melange Dune extension is independent of the version of Melange we’re using.

Technically, dune-project accepts many more metadata fields, but it’s best to keep it minimal. Other than name, it makes more sense to put the rest of your project’s metadata fields in your .opam file, which we’ll cover later.

dune-project files use S-expressions, which might make you think of the Lisp programming language. However, S-expressions are just a convenient syntax for encoding structured data, and Dune doesn’t have the power of a full scripting language.

Each S-expression at the top level is a known as a stanza. All the possible stanzas you can use in dune-project can be found in Dune’s Stanza Reference.

dune files

Besides dune-project, Dune also looks at the dune files in our project. Basically, dune files tell Dune about directories, executables, libraries, tests, and anything else of interest. For example, here’s the dune file inside the root directory of your project:

clj
; \`dirs\` is a stanza to tell dune which subfolders from the current folder
+; (where the \`dune\` file is) it should process. Here it is saying to include
+; all directories that don't start with . or _, but exclude node_modules.
+
+(dirs :standard \\ node_modules)
+
+; \`melange.emit\` is a Dune stanza that will produce build rules to generate
+; JavaScript files from sources using the Melange compiler
+; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
+
+(melange.emit
+ ; The \`target\` field is used by Dune to put all JavaScript artifacts in a
+ ; specific folder inside \`_build/default\`
+ (target output)
+ ; Here's the list of dependencies of the stanza. In this case (being
+ ; \`melange.emit\`), Dune will look into those dependencies and generate rules
+ ; with JavaScript targets for the modules in those libraries as well.
+ ; Caveat: the libraries need to be specified with \`(modes melange)\`.
+ (libraries reason-react)
+ ; The \`preprocess\` field lists preprocessors which transform code before it is
+ ; compiled. melange.ppx allows to use Melange attributes [@mel. ...]
+ ; (https://melange.re/v2.0.0/communicate-with-javascript/#attributes)
+ ; reason-react-ppx allows to use JSX for ReasonReact components by using the
+ ; [@JSX] attributes from Reason: https://reasonml.github.io/docs/en/jsx
+ (preprocess
+  (pps melange.ppx reason-react-ppx))
+ ; module_systems lets you specify commonjs (the default) or es6
+ (module_systems es6))
; \`dirs\` is a stanza to tell dune which subfolders from the current folder
+; (where the \`dune\` file is) it should process. Here it is saying to include
+; all directories that don't start with . or _, but exclude node_modules.
+
+(dirs :standard \\ node_modules)
+
+; \`melange.emit\` is a Dune stanza that will produce build rules to generate
+; JavaScript files from sources using the Melange compiler
+; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
+
+(melange.emit
+ ; The \`target\` field is used by Dune to put all JavaScript artifacts in a
+ ; specific folder inside \`_build/default\`
+ (target output)
+ ; Here's the list of dependencies of the stanza. In this case (being
+ ; \`melange.emit\`), Dune will look into those dependencies and generate rules
+ ; with JavaScript targets for the modules in those libraries as well.
+ ; Caveat: the libraries need to be specified with \`(modes melange)\`.
+ (libraries reason-react)
+ ; The \`preprocess\` field lists preprocessors which transform code before it is
+ ; compiled. melange.ppx allows to use Melange attributes [@mel. ...]
+ ; (https://melange.re/v2.0.0/communicate-with-javascript/#attributes)
+ ; reason-react-ppx allows to use JSX for ReasonReact components by using the
+ ; [@JSX] attributes from Reason: https://reasonml.github.io/docs/en/jsx
+ (preprocess
+  (pps melange.ppx reason-react-ppx))
+ ; module_systems lets you specify commonjs (the default) or es6
+ (module_systems es6))

Like dune-project, a dune file consists of one or more stanzas. The first stanza is dirs, which tells Dune which directories to include in the build. Note that the stanzas accepted in dune files are not the same as the ones accepted by dune-project. See all possible dune stanzas in Dune’s Stanza Reference.

melange.emit stanza

The main stanza of interest for us is melange.emit, which tells Dune to turn our OCaml files into JavaScript files. The fields we give to melange.emit here are target, libraries, preprocess, and module_systems, which are ones that we need to use for pretty much every Melange project.

A note about the target field: It is referenced in the serve npm script, whose command is

bash
webpack serve --open --mode development --entry ./_build/default/output/Index.js
webpack serve --open --mode development --entry ./_build/default/output/Index.js

If you change the value of target to, say, stuff, the value of the --entry option must be changed to

./_build/default/stuff/Index.js
./_build/default/stuff/Index.js

For more details about where JavaScript output files end up in the build directory, see JavaScript artifacts layout.

INFO

In this dune file, we’re only concerned with building JavaScript to run in the browser, but if we also wanted to build JavaScript to run on Node, we’d include another melange.emit stanza specifically for that. See melange-opam-template for an example of building for Node.

Counter app directory

Create a new directory src/counter, which will contain a new app that only renders the Counter component. Then make sure this new directory contains:

  • Counter.re (move from root directory to src/counter)

  • dune file that just has a melange.emit stanza

    clj
    ; \`melange.emit\` is a Dune stanza that will produce build rules to generate
    +; JavaScript files from sources using the Melange compiler
    +; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
    +
    +(melange.emit
    + ; The \`target\` field is used by Dune to put all JavaScript artifacts in a
    + ; specific folder inside \`_build/default\`
    + (target output)
    + ; Here's the list of dependencies of the stanza. In this case (being
    + ; \`melange.emit\`), Dune will look into those dependencies and generate rules
    + ; with JavaScript targets for the modules in those libraries as well.
    + ; Caveat: the libraries need to be specified with \`(modes melange)\`.
    + (libraries reason-react)
    + ; The \`preprocess\` field lists preprocessors which transform code before it is
    + ; compiled. These enable, for example, the use of JSX in .re files.
    + (preprocess
    +  (pps melange.ppx reason-react-ppx))
    + ; module_systems lets you specify commonjs (the default) or es6
    + (module_systems es6))
    ; \`melange.emit\` is a Dune stanza that will produce build rules to generate
    +; JavaScript files from sources using the Melange compiler
    +; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
    +
    +(melange.emit
    + ; The \`target\` field is used by Dune to put all JavaScript artifacts in a
    + ; specific folder inside \`_build/default\`
    + (target output)
    + ; Here's the list of dependencies of the stanza. In this case (being
    + ; \`melange.emit\`), Dune will look into those dependencies and generate rules
    + ; with JavaScript targets for the modules in those libraries as well.
    + ; Caveat: the libraries need to be specified with \`(modes melange)\`.
    + (libraries reason-react)
    + ; The \`preprocess\` field lists preprocessors which transform code before it is
    + ; compiled. These enable, for example, the use of JSX in .re files.
    + (preprocess
    +  (pps melange.ppx reason-react-ppx))
    + ; module_systems lets you specify commonjs (the default) or es6
    + (module_systems es6))
  • Index.re to render the app to the DOM

    re
    module App = {
    +  [@react.component]
    +  let make = () => <Counter />;
    +};
    +
    +let node = ReactDOM.querySelector("#root");
    +switch (node) {
    +| None =>
    +  Js.Console.error("Failed to start React: couldn't find the #root element")
    +| Some(root) => ReactDOM.render(<App />, root)
    +};
    module App = {
    +  [@react.component]
    +  let make = () => <Counter />;
    +};
    +
    +let node = ReactDOM.querySelector("#root");
    +switch (node) {
    +| None =>
    +  Js.Console.error("Failed to start React: couldn't find the #root element")
    +| Some(root) => ReactDOM.render(<App />, root)
    +};
  • Makefile to serve the app using webpack dev server

    make
    .PHONY: serve
    +serve:
    +	app=counter make -C ../.. serve
    .PHONY: serve
    +serve:
    +	app=counter make -C ../.. serve

After you’ve added those files, your src/counter directory should look like this:

src/counter
+├─ Counter.re
+├─ dune
+├─ Index.re
+└─ Makefile
src/counter
+├─ Counter.re
+├─ dune
+├─ Index.re
+└─ Makefile

Why Makefile

You might be wondering why we’re using a Makefile instead of adding another npm script. In OCaml projects, usage of the Make build automation tool is common, and this includes Melange-related projects. So let’s take a short detour to explain the Makefile we just added.

Anatomy of Makefile

In case you’re not familiar with Make, here’s a breakdown of src/counter/Makefile:

make
.PHONY: serve
+serve:
+	app=counter make -C ../.. serve
.PHONY: serve
+serve:
+	app=counter make -C ../.. serve
  • There’s only a single rule here, and its target is serve.
  • .PHONY: serve is used to indicate that serve is a phony target, meaning serve is not a file we want to generate but just a label for an action. In a simple Makefile like this one, declaring phony targets isn’t strictly necessary.
  • The line under serve: is the recipe, basically the command that will be executed when we run make serve at the command line.
    • app=counter sets the app environment variable to counter, which is the name of the directory this Makefile lives in
    • The -C option tells Make to change the directory before reading the Makefile. In effect, it means we’re running the serve rule in the root directory’s Makefile.

Root directory Makefile

Currently, the serve rule in root directory’s Makefile can only run the app in the root directory. We want it to be able to run the app in src/counter, so we need to change it:

make
.PHONY: serve
+serve: ## Serve the application with a local HTTP server
+	npx webpack serve --open --mode development --entry ./_build/default/src/$(app)/output/src/$(app)/Index.js
.PHONY: serve
+serve: ## Serve the application with a local HTTP server
+	npx webpack serve --open --mode development --entry ./_build/default/src/$(app)/output/src/$(app)/Index.js

We basically copied the serve npm command from package.json to create the recipe for this rule, but instead of a fixed value for the --entry option, we use

./_build/default/src/$(app)/output/src/$(app)/Index.js
./_build/default/src/$(app)/output/src/$(app)/Index.js

This means that the entry script served by webpack dev server depends on the app environment variable, which is provided by src/counter/Makefile.

You’re now ready to run the new Counter app you created! Go into the src/counter directory and run

make serve
make serve

It should open a new tab in your default browser to http://localhost:8080/ and display your Counter component.

Cleanup

Feel to delete the Index.re file in the root directory. You won’t need it anymore for this or later chapters. You can also delete:

  • The scripts section of yourpackage.json file
  • The melange.emit stanza from the dune file in the root directory

Rationale for monorepo structure

Going forward, we’re going to use a monorepo where projects are separate apps that are developed in their own directory. Each project directory will have its own dune file with its own melange.emit stanza. We want to use a monorepo because most projects will have very similar dependencies, so it seems overkill to create new dune-project, .opam, and package.json files[1] for every single project.

INFO

Melange documentation’s guidelines for melange.emit recommends you put the melange.emit stanza in the dune file in the project’s root directory. We are no longer doing that going forward, but this is still great advice if your repo only contains a single app!

Huzzah! You created a new dune file to build an app and a Makefile to serve that app locally. In future chapters, we assume that you will use the same directory structure for each new app you build.

Exercises

1. Repeat the steps we did for Counter and create a separate app for Celsius Converter.

2. Delete reason-react-ppx from src/counter/dune’s melange.emit stanza. What compiler errors do you get?

3. You might have noticed that every recipe in the Makefile is prefixed by a tab. What happens if you replace the tab in front of the serve rule’s recipe with four spaces?

Overview

  • Dune is the build system we use to build Melange projects
  • The dune-project file describes the metadata for your project, primarily:
    • The version of Dune you’re using
    • The version of the Melange plugin for Dune you’re using
    • The name of your project
  • dune files describe things of interest to Dune, for example:
    • Which directories to include and which to exclude
    • Which directories contain code that should be transpiled to JavaScript, using the melange.emit stanza
  • Make is a build automation tool commonly used in the OCaml world
    • Makefiles contain rules which can run commands based on the target you pass to the make command

Solutions

1. Creating a separate app for Celsius Converter, with its own dune, Makefile, and Index.re files, should look something like this.

2. Deleting reason-react-ppx from src/counter/dune will result in a compilation error:

File "src/counter/Counter.re", line 5, characters 2-6:
+5 |   <div
+      ^^^^
+Error: Unbound value div
File "src/counter/Counter.re", line 5, characters 2-6:
+5 |   <div
+      ^^^^
+Error: Unbound value div

That’s because putting reason-react-ppx in the preprocess/pps field will transform function calls to div (which isn’t defined anywhere) into calls to React.createElement("div", ...)[2].

3. Replacing the tab in front of the serve rule’s recipe with four spaces will result in a Makefile error:

Makefile:42: *** missing separator.  Stop.
Makefile:42: *** missing separator.  Stop.

The line number where it expects the tab is 42. It is a very common mistake to write spaces instead of tabs in a Makefile. Fortunately, most code editors know that when you press the Tab key inside a Makefile, you mean to add a tab character instead of space characters.


Source code for this chapter can be found in the Melange for React Developers repo:


  1. The full list of files we’d need to create for every project would actually be dune-project, .opam, package.json, public/index.html, and webpack.config.js. ↩︎

  2. More details about how JSX gets translated can be found here and here. ↩︎

`,69),p=[l];function t(r,c,i,d,u,y){return s(),a("div",null,p)}const m=e(o,[["render",t]]);export{E as __pageData,m as default}; diff --git a/assets/intro-to-dune_index.md.a5b8b6ca.lean.js b/assets/intro-to-dune_index.md.a5b8b6ca.lean.js new file mode 100644 index 00000000..367497fc --- /dev/null +++ b/assets/intro-to-dune_index.md.a5b8b6ca.lean.js @@ -0,0 +1 @@ +import{_ as e,o as s,c as a,Q as n}from"./chunks/framework.0e8ae64e.js";const E=JSON.parse('{"title":"Introduction to Dune","description":"","frontmatter":{},"headers":[],"relativePath":"intro-to-dune/index.md","filePath":"intro-to-dune/index.md"}'),o={name:"intro-to-dune/index.md"},l=n("",69),p=[l];function t(r,c,i,d,u,y){return s(),a("div",null,p)}const m=e(o,[["render",t]]);export{E as __pageData,m as default}; diff --git a/assets/intro_index.md.987c5fae.js b/assets/intro_index.md.987c5fae.js new file mode 100644 index 00000000..c65cb7d5 --- /dev/null +++ b/assets/intro_index.md.987c5fae.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as a,Q as o}from"./chunks/framework.0e8ae64e.js";const m=JSON.parse('{"title":"Melange for React Developers","description":"","frontmatter":{},"headers":[],"relativePath":"intro/index.md","filePath":"intro/index.md"}'),r={name:"intro/index.md"},n=o('

Melange for React Developers

WARNING

This is a work in progress.

Motivation

This is a project-based, guided introduction to Melange and its ecosystem. Because Melange uses both OCaml and JavaScript ecosystems, there are quite a few tools and concepts to learn. Therefore we try to make each chapter small and digestible, not introducing too many things at once.

Audience

You should already know how to make frontend applications in JavaScript, in particular with React. You should be interested in learning how to leverage your existing knowledge to build apps using ReasonReact. You do not need to know OCaml[1]—we’ll slowly introduce the basics of the language throughout the tutorial. That said, a good complement to this guide is OCaml Programming: Correct + Efficient + Beautiful, which teaches the language from the ground up and goes much deeper into its features.

Chapters and topics

TitleSummaryTopics covered
CounterNumber that can be incremented or decrementedmodule, Option, pipe last operator, function chaining, switch
Melange PlaygroundUse Melange Playground to explore OCaml’s numeric typesPlayground, Int, Float
Celsius ConverterSingle input that converts from Celsius to Fahrenheitpolymorphic object, exception handling, ternary expression, if-else expression, labeled argument, partial application
Celsius Converter using OptionThe same component from the last chapter but replacing exception handling with OptionOption, Option.map, when guard

…and much more to come!


  1. Because of the focus on ReasonReact, we won’t cover traditional OCaml syntax in this guide. Instead, we’ll cover the Reason syntax which works great with ReasonReact because of its first-class support for JSX. ↩︎

',11),i=[n];function s(l,c,d,h,p,u){return t(),a("div",null,i)}const g=e(r,[["render",s]]);export{m as __pageData,g as default}; diff --git a/assets/intro_index.md.987c5fae.lean.js b/assets/intro_index.md.987c5fae.lean.js new file mode 100644 index 00000000..956bb2f0 --- /dev/null +++ b/assets/intro_index.md.987c5fae.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as a,Q as o}from"./chunks/framework.0e8ae64e.js";const m=JSON.parse('{"title":"Melange for React Developers","description":"","frontmatter":{},"headers":[],"relativePath":"intro/index.md","filePath":"intro/index.md"}'),r={name:"intro/index.md"},n=o("",11),i=[n];function s(l,c,d,h,p,u){return t(),a("div",null,i)}const g=e(r,[["render",s]]);export{m as __pageData,g as default}; diff --git a/assets/numeric-types_index.md.6aeeacfe.js b/assets/numeric-types_index.md.6aeeacfe.js new file mode 100644 index 00000000..9bce040a --- /dev/null +++ b/assets/numeric-types_index.md.6aeeacfe.js @@ -0,0 +1,242 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const D=JSON.parse('{"title":"Numeric Types","description":"","frontmatter":{},"headers":[],"relativePath":"numeric-types/index.md","filePath":"numeric-types/index.md"}'),o={name:"numeric-types/index.md"},p=l(`

Numeric Types

OCaml’s numeric types work differently than in JavaScript. The first thing you might notice is that OCaml makes a clear and hard distinction between integer and float types. For example:

reason
let foo = 42;   // int
+let bar = 42.1; // float
+Js.log(foo);
+Js.log(bar);
let foo = 42;   // int
+let bar = 42.1; // float
+Js.log(foo);
+Js.log(bar);

Note that you didn’t have to write the types yourself, OCaml is able to infer the types from the literals. This would also work:

reason
let foo: int = 42;
+let bar: float = 42.1;
+Js.log(foo);
+Js.log(bar);
let foo: int = 42;
+let bar: float = 42.1;
+Js.log(foo);
+Js.log(bar);

Melange Playground

Melange Playground is an interactive environment for running OCaml code and seeing its output. Paste this into the source code editor on the left side:

reason
let foo = 42;
+let bar = 42.1;
+Js.log(foo);
+Js.log(bar);
let foo = 42;
+let bar = 42.1;
+Js.log(foo);
+Js.log(bar);

In the bottom right panel, you can see the console output, which should be:

42
+42.1
42
+42.1

In the top right panel, you can see the JavaScript generated by the Melange compiler:

// Generated by Melange
+
+
+console.log(42);
+
+console.log(42.1);
+
+var foo = 42;
+
+var bar = 42.1;
+
+export {
+  foo ,
+  bar ,
+}
+/*  Not a pure module */
// Generated by Melange
+
+
+console.log(42);
+
+console.log(42.1);
+
+var foo = 42;
+
+var bar = 42.1;
+
+export {
+  foo ,
+  bar ,
+}
+/*  Not a pure module */

Note that the console.log invocations are given constants instead of the variables. That’s a nifty optimization done by Melange.

Another sweet feature is that you can hover over the variables and see their types. Try it out, and you’ll see that foo has type int while bar has type float.

The Problems pane in the bottom left corner shows error mesages when appropriate. At the moment, it shows No problems. Try type-annotating bar with int and see what happens:

reason
let foo = 42; // int
+let bar: int = 42.1; // float
+Js.log(foo);
+Js.log(bar);
let foo = 42; // int
+let bar: int = 42.1; // float
+Js.log(foo);
+Js.log(bar);

The Problems pane should now show something like this:

Line 2, 15:
+  Error This expression has type float but an expression was expected of type int
Line 2, 15:
+  Error This expression has type float but an expression was expected of type int

Sharing code snippets

Melange Playground is also an excellent way to share OCaml code snippets with your friends! As you type in the source editor, it will store your code in the code query string parameter of the URL. For example, here’s a link to the snippet we started with:

https://melange.re/v2.1.0/playground/?language=Reason&code=bGV0IGZvbyA9IDQyOwpsZXQgYmFyID0gNDIuMTsKSnMubG9nKGZvbyk7CkpzLmxvZyhiYXIpOw%3D%3D&live=off

Comparison operators

In Melange Playground, change your program to this:

reason
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(foo == bar);
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(foo == bar);

You’ll get a compiler error for the last line that says

This expression has type float but an expression was expected of type int
This expression has type float but an expression was expected of type int

Unlike JavaScript, there are no implicit conversions in OCaml. Therefore you cannot expect to compare an integer and a float together, unless you convert one of the values so that both values have the same type. To make the last line compile, you can change it to:

reason
Js.log(foo == Int.of_float(bar));
Js.log(foo == Int.of_float(bar));

Another way to fix the last line is to convert foo from an int to a float:

reason
Js.log(Float.of_int(foo) == bar);
Js.log(Float.of_int(foo) == bar);

The same-type restriction applies to all the comparison operators:

reason
Js.log(3 < 33);
+Js.log(44. > 4.);
+Js.log(5 <= 55);
+Js.log(66. >= 6.);
Js.log(3 < 33);
+Js.log(44. > 4.);
+Js.log(5 <= 55);
+Js.log(66. >= 6.);

Arithmetic operators

What about addition? From what you’ve already seen, you can probably guess that Js.log(42 + 16.0) won’t compile. However, you may be surprised to discover that Js.log(42.0 + 16.0) also won’t compile! That’s because OCaml uses separate arithmetic operators for floats. What will compile is this:

reason
Js.log(42.0 +. 16.0); // prints 58
Js.log(42.0 +. 16.0); // prints 58

Here are examples of the other arithmetic operators, try them out in the playground:

reason
Js.log(66.0 -. 6.0);
+Js.log(66.0 *. 6.0);
+Js.log(66.0 /. 6.0);
Js.log(66.0 -. 6.0);
+Js.log(66.0 *. 6.0);
+Js.log(66.0 /. 6.0);

Notice that all float arithmetic operators end with . (period), just like float literals.

They’re just Number

Underneath the covers, foo and bar are both instances of JavaScript’s Number type:

reason
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(Js.typeof(foo)); // prints "number"
+Js.log(Js.typeof(bar)); // prints "number"
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(Js.typeof(foo)); // prints "number"
+Js.log(Js.typeof(bar)); // prints "number"

Refer to the Melange docs for a complete rundown of how OCaml types get translated to JavaScript types.

Widgets in the playground

Melange Playground can also render ReasonReact components! Click the Live button next to the JavaScript output button. Now paste in the code to render the Counter component from the previous chapter:

re
module Counter = {
+  [@react.component]
+  let make = () => {
+    let (counter, setCounter) = React.useState(() => 0);
+
+    <div
+      style={ReactDOMStyle.make(
+        ~padding="1em",
+        ~display="flex",
+        ~gridGap="1em",
+        (),
+      )}>
+      <button onClick={_evt => setCounter(v => v - 1)}>
+        {React.string("-")}
+      </button>
+      <span> {counter |> Int.to_string |> React.string} </span>
+      <button onClick={_evt => setCounter(v => v + 1)}>
+        {React.string("+")}
+      </button>
+    </div>;
+  };
+};
+
+switch (ReactDOM.querySelector("#preview")) {
+| None => Js.log("Failed to start React: couldn't find the #preview element")
+| Some(root) => ReactDOM.render(<Counter />, root)
+};
module Counter = {
+  [@react.component]
+  let make = () => {
+    let (counter, setCounter) = React.useState(() => 0);
+
+    <div
+      style={ReactDOMStyle.make(
+        ~padding="1em",
+        ~display="flex",
+        ~gridGap="1em",
+        (),
+      )}>
+      <button onClick={_evt => setCounter(v => v - 1)}>
+        {React.string("-")}
+      </button>
+      <span> {counter |> Int.to_string |> React.string} </span>
+      <button onClick={_evt => setCounter(v => v + 1)}>
+        {React.string("+")}
+      </button>
+    </div>;
+  };
+};
+
+switch (ReactDOM.querySelector("#preview")) {
+| None => Js.log("Failed to start React: couldn't find the #preview element")
+| Some(root) => ReactDOM.render(<Counter />, root)
+};

Note that we explicitly defined a module for the Counter component this time because we can’t use multiple files in Melange Playground.

Let’s make the counter look a little more impressive. Add a new module called Styles which contains all the styles we want to use:

re
module Styles = {
+  // Alias the function to save on keystrokes
+  let make = ReactDOMStyle.make;
+
+  let root =
+    make(
+      ~fontSize="2em",
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      ~alignItems="center",
+      (),
+    );
+
+  let button =
+    make(
+      ~fontSize="1em",
+      ~border="1px solid white",
+      ~borderRadius="0.5em",
+      ~padding="0.5em",
+      (),
+    );
+
+  let number = make(~minWidth="2em", ~textAlign="center", ());
+};
module Styles = {
+  // Alias the function to save on keystrokes
+  let make = ReactDOMStyle.make;
+
+  let root =
+    make(
+      ~fontSize="2em",
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      ~alignItems="center",
+      (),
+    );
+
+  let button =
+    make(
+      ~fontSize="1em",
+      ~border="1px solid white",
+      ~borderRadius="0.5em",
+      ~padding="0.5em",
+      (),
+    );
+
+  let number = make(~minWidth="2em", ~textAlign="center", ());
+};

And then update the JSX in our make function to use the style objects in Styles:

re
<div style=Styles.root>
+  <button style=Styles.button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span style=Styles.number>
+    {counter |> Int.to_string |> React.string}
+  </span>
+  <button style=Styles.button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;
<div style=Styles.root>
+  <button style=Styles.button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span style=Styles.number>
+    {counter |> Int.to_string |> React.string}
+  </span>
+  <button style=Styles.button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;

Here’s the playground link for the fully-styled Counter component.

W00t! You are now empowered to use numbers in your OCaml programs.

Exercises

1. Convert the Counter component we created in the previous chapter to use float instead of integer. Make the - button decrement by 0.5 and the + button increment by 1.5.

2. Add an int64 value to your program in Melange Playground:

reason
let baz = 42_000_000_000L; // int64
+Js.log(baz);
let baz = 42_000_000_000L; // int64
+Js.log(baz);

Note the use of underscores to make the large number more readable. What is the JavaScript representation of int64?

3. How do you add two int64 values? Hint: Take a look at the standard library’s Int64 module.

Overview

  • Integer and float are separate types in OCaml, but both translate to JavaScript’s Number type once your program is compiled
  • Comparison operators expect the values on both sides to be the same type
  • Integer arithmetic operators are the same as in JavaScript, but float arithmetic operators are different (they end with .) and only accept floats as inputs
  • Melange Playground is a great way to play around with short OCaml programs and has many helpful features:
    • Display console output
    • Display compiled JavaScript output
    • Display error messages when your code isn’t compiling
    • Show type hints on hover
    • Share code snippets via URL
    • Render ReasonReact components

Solutions

1. A Counter component that uses float instead of integer would look something like this:

re
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0.0);
+
+  <div
+    style={ReactDOMStyle.make(
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      (),
+    )}>
+    <button onClick={_evt => setCounter(v => v -. 0.5)}>
+      {React.string("-")}
+    </button>
+    <span> {counter |> Float.to_string |> React.string} </span>
+    <button onClick={_evt => setCounter(v => v +. 1.5)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0.0);
+
+  <div
+    style={ReactDOMStyle.make(
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      (),
+    )}>
+    <button onClick={_evt => setCounter(v => v -. 0.5)}>
+      {React.string("-")}
+    </button>
+    <span> {counter |> Float.to_string |> React.string} </span>
+    <button onClick={_evt => setCounter(v => v +. 1.5)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};

2. JavaScript’s Number type doesn’t have enough precision to represent in64 values. They’re instead represented by an array of two numbers [high, low], where high is signed, low is unsigned.

3. You can add two int64 values using Int64.add, e.g.

reason
let result = Int64.add(42L, 16L);
+Js.log(result); // prints [0,58]
let result = Int64.add(42L, 16L);
+Js.log(result); // prints [0,58]

Source code for this chapter can be found in the Melange for React Developers repo.

`,68),e=[p];function t(c,r,y,E,i,F){return n(),a("div",null,e)}const d=s(o,[["render",t]]);export{D as __pageData,d as default}; diff --git a/assets/numeric-types_index.md.6aeeacfe.lean.js b/assets/numeric-types_index.md.6aeeacfe.lean.js new file mode 100644 index 00000000..4e204cf9 --- /dev/null +++ b/assets/numeric-types_index.md.6aeeacfe.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,Q as l}from"./chunks/framework.0e8ae64e.js";const D=JSON.parse('{"title":"Numeric Types","description":"","frontmatter":{},"headers":[],"relativePath":"numeric-types/index.md","filePath":"numeric-types/index.md"}'),o={name:"numeric-types/index.md"},p=l("",68),e=[p];function t(c,r,y,E,i,F){return n(),a("div",null,e)}const d=s(o,[["render",t]]);export{D as __pageData,d as default}; diff --git a/assets/order-confirmation_index.md.c17c7e32.js b/assets/order-confirmation_index.md.c17c7e32.js new file mode 100644 index 00000000..35c8c4ce --- /dev/null +++ b/assets/order-confirmation_index.md.c17c7e32.js @@ -0,0 +1,295 @@ +import{_ as s,o as a,c as n,Q as l}from"./chunks/framework.0e8ae64e.js";const B=JSON.parse('{"title":"Order Confirmation","description":"","frontmatter":{},"headers":[],"relativePath":"order-confirmation/index.md","filePath":"order-confirmation/index.md"}'),o={name:"order-confirmation/index.md"},p=l(`

Order Confirmation

The famed restauranteur Madame Jellobutter has opened a hot new pop-up restaurant called Emoji Cafe, and you’ve been commissioned to build the order confirmation widget on its website. Feeling adventurous, you decide to build it using Melange.

Start by creating a new directory src/order-confirmation and give it the same directory structure as we showed you in the previous chapter:

src/order-confirmation
+├─ dune
+├─ Index.re
+├─ Makefile
+└─ Item.re
src/order-confirmation
+├─ dune
+├─ Index.re
+├─ Makefile
+└─ Item.re

The dune file can be copied from any of the existing projects. The Makefile can also be copied over, but remember to update the value of the app environment variable to order-confirmation. The .re files can be empty for now.

Variant type Item.t

For the time being, there are only two items you can order at Emoji Cafe, the sandwich or the burger. In Item.re, add a new type:

re
type t =
+  | Sandwich
+  | Burger;
type t =
+  | Sandwich
+  | Burger;

This is a variant type[1] named t with two constructors, Sandwich and Burger. In OCaml, it is customary for the primary type of a module to be called t. This convention makes sense because in other modules, this type will be referred to as Item.t.

The Item module should contain helper functions that return the price and the emoji[2] for a given item. First, add the toPrice function:

re
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 15.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 15.
+  };

If Madame Jellobutter decides to add a hotdog to the menu, you would need to:

  • Add a Hotdog constructor to Order.t
  • Add a | Hotdog branch to the switch expression of Order.toPrice

Your OCaml code would fail to compile if you added Hotdog or removed Sandwich from Item.t without also updating Item.toPrice. This is one of the great advantages of variant types: changing the constructors will force you to change the relevant parts of your code.

Wildcard in switch expressions

If Madame Jellobutter decides to do a promotion that lowers the price of burgers so that they’re the same price as sandwiches, you could rewrite Item.toPrice to:

reason
let toPrice = t =>
+  switch (t) {
+  | _ => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | _ => 10.
+  };

The underscore (_) here serves as a wildcard matching any constructor. However, this would be a very bad idea! Now changing the constructors in Item.t would not force you to change Item.toPrice accordingly. A superior version would be:

reason
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 10.
+  };

Since OCaml’s pattern-matching syntax allows you to combine branches, you can simplify it to:

reason
let toPrice = t =>
+  switch (t) {
+  | Sandwich
+  | Burger => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich
+  | Burger => 10.
+  };

In any case, you should strive to avoid wildcards. The OCaml Way is to explicitly match all constructors in your switch expressions.

A fun syntax for switch

There’s an alternate, shorter syntax for functions whose entire body is a switch expression. It’s called fun, and we can rewrite Item.toPrice to use it:

re
let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.;
let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.;

We can also define toEmoji using the fun syntax:

re
let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js};
let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js};

Using the fun syntax is completely equivalent to using a switch expression, so it’s up to your personal taste whether you want to use one or the other.

Item.make

Now we’re ready to define the make function which will render the Item component:

re
[@react.component]
+let make = (~item: t) =>
+  <tr>
+    <td> {item |> toEmoji |> React.string} </td>
+    <td>
+      {item
+       |> toPrice
+       |> Js.Float.toFixedWithPrecision(~digits=2)
+       |> React.string}
+    </td>
+  </tr>;
[@react.component]
+let make = (~item: t) =>
+  <tr>
+    <td> {item |> toEmoji |> React.string} </td>
+    <td>
+      {item
+       |> toPrice
+       |> Js.Float.toFixedWithPrecision(~digits=2)
+       |> React.string}
+    </td>
+  </tr>;

The make function has a single labeled argument, ~item, of type Item.t. This effectively means the Item component has a single prop named item.

Note that this renders a single row of a table. We’ll need another component to render a table containing all items in an order.

Order component

Create a new file src/order-confirmation/Order.re and add the following code:

re
type t = array(Item.t);
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items
+    |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items |> Js.Array.map(item => <Item item />) |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td>
+          {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+        </td>
+      </tr>
+    </tbody>
+  </table>;
+};
type t = array(Item.t);
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items
+    |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items |> Js.Array.map(item => <Item item />) |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td>
+          {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+        </td>
+      </tr>
+    </tbody>
+  </table>;
+};

There’s a lot going on here:

  • The primary type of Order is array(Item.t), which is an array of variants.
  • The Order.make function has a single labeled argument, ~items, of type t. This means the Order component has a single prop named items.
  • We sum up the prices of all items using Js.Array.reduce, which is the Melange binding to JavaScript’s Array.reduce method. Note that Js.Array.reduce requires the initial value to be passed in.
  • For each order, we render an Item component via Js.Array.map, which is the Melange binding to the Array.map method.

React.array

You might have noticed that we need a call to React.array after the call to Js.Array.map:

reason
{items |> Js.Array.map(item => <Item item />) |> React.array}
{items |> Js.Array.map(item => <Item item />) |> React.array}

If we leave off the call to React.array, we’d get this error:

File "src/order-confirmation/Order.re", lines 12, characters 6-12:
+12 |         {items |> Js.Array.map(item => <Item item />)}
+             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This expression has type React.element array
+       but an expression was expected of type React.element
File "src/order-confirmation/Order.re", lines 12, characters 6-12:
+12 |         {items |> Js.Array.map(item => <Item item />)}
+             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This expression has type React.element array
+       but an expression was expected of type React.element

We get this error primarily because collections in OCaml can only contain elements of the same type. The tbody element expects children of type React.element[3], but the call to Js.Array.map returns array(React.element), which creates a type mismatch. To make the actual type match the expected type, we must add a call to React.array which turns array(React.element) to React.element.

To better see what types are at play, it might make sense to refactor Order.make like so:

re
let total =
+  items
+  |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+let itemRows: array(React.element) =
+  items |> Js.Array.map(item => <Item item />);
+
+<table>
+  <tbody>
+    {itemRows |> React.array}
+    <tr>
+      <td> {React.string("Total")} </td>
+      <td>
+        {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+      </td>
+    </tr>
+  </tbody>
+</table>;
let total =
+  items
+  |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+let itemRows: array(React.element) =
+  items |> Js.Array.map(item => <Item item />);
+
+<table>
+  <tbody>
+    {itemRows |> React.array}
+    <tr>
+      <td> {React.string("Total")} </td>
+      <td>
+        {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+      </td>
+    </tr>
+  </tbody>
+</table>;

In reality, React.array is just there to make the OCaml compiler happy—it doesn’t actually change the the underlying JavaScript object. For example, try running the following code in the playground:

re
let elemArray: array(React.element) =
+  [|"a", "b", "c"|] |> Js.Array.map(x => React.string(x));
+Js.log(elemArray);
+Js.log(React.array(elemArray));
let elemArray: array(React.element) =
+  [|"a", "b", "c"|] |> Js.Array.map(x => React.string(x));
+Js.log(elemArray);
+Js.log(React.array(elemArray));

If you look at the JavaScript output, you’ll see that the two calls to Js.log get compiled to

javascript
console.log(elemArray);
+
+console.log(elemArray);
console.log(elemArray);
+
+console.log(elemArray);

Index.re

Render the Order component inside src/order-confirmation/Index.re:

re
module App = {
+  let items: Order.t = [|Sandwich, Burger, Sandwich|];
+
+  [@react.component]
+  let make = () =>
+    <div>
+      <h1> {React.string("Order confirmation")} </h1>
+      <Order items />
+    </div>;
+};
+
+let node = ReactDOM.querySelector("#root");
+switch (node) {
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+| Some(root) => ReactDOM.render(<App />, root)
+};
module App = {
+  let items: Order.t = [|Sandwich, Burger, Sandwich|];
+
+  [@react.component]
+  let make = () =>
+    <div>
+      <h1> {React.string("Order confirmation")} </h1>
+      <Order items />
+    </div>;
+};
+
+let node = ReactDOM.querySelector("#root");
+switch (node) {
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+| Some(root) => ReactDOM.render(<App />, root)
+};

Run make serve inside src/order-confirmation to see your new app in action.

Js.Array.mapi

Open your browser’s dev console, where you should see a warning:

Warning: Each child in a list should have a unique "key" prop.
Warning: Each child in a list should have a unique "key" prop.

Oops, we forgot the set the key props! One way to fix this is to use Js.Array.mapi instead[4] so we can set key based on the index of the element:

re
items
+|> Js.Array.mapi((item, index) =>
+     <Item key={"item-" ++ string_of_int(index)} item />
+   )
+|> React.array
items
+|> Js.Array.mapi((item, index) =>
+     <Item key={"item-" ++ string_of_int(index)} item />
+   )
+|> React.array

The Js.Array.mapi function is also a binding to the Array.map method, but unlike Js.Array.map, it passes the element and the index into the callback. If you hover over it, you’ll see that it has the type signature

(('a, int) => 'b, array('a)) => array('b)
(('a, int) => 'b, array('a)) => array('b)

When a JavaScript function has optional arguments, it’s common to create multiple OCaml functions that bind to it. We’ll discuss this in more detail later.


Wunderbar! You’ve got a basic order confirmation component, but it looks… not so great[5]. In the next chapter, we’ll see how ReasonReact components can be styled with plain old CSS.

Exercises

1. The Item component is only used inside the Order component and we don’t expect it to be used anywhere else (items rendered in a menu component would look different). Rename it to OrderItem and move it inside the Order module.

2. Add another constructor to Item.t variant type. Update the Item module’s helper functions to get your program to compile again.

3. Instead of repeatedly using value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string, add a helper function Format.currency that does the same thing.

Overview

  • By convention, the main type in a module is often named t
  • A variant is a type that has one or more constructors
    • Adding or removing constructors forces you to change the relevant parts of your code, unless you use wildcards when pattern-matching on a variant
    • Using wildcards in your switch expression makes your code less adaptable to change
  • The fun syntax helps you save a little bit of typing when you have a function whose entire body is a switch expression
  • Labeled arguments in a component’s make function are treated as props by ReasonReact.
  • The Js.Array module contains useful array functions
    • The Js.Array.reduce function is the binding to JavaScript’s Array.reduce method
    • The Js.Array.map and Js.Array.mapi functions are both bindings to JavaScript’s Array.map method
  • The React.array function is needed when you want to convert an array of React.elements to a single React.element, e.g. after a call to Js.Array.map

Solutions

1. To move the Item component from the Item module to the Order module, you’ll have to move the Item.make function to a submodule called Order.OrderItem. Then you’ll have to prefix the references to t, toPrice, and toEmoji with Item. since they’re now being referenced outside the Item module. After you’re done, src/order-confirmation/Order.re should look something like this:

re
type t = array(Item.t);
+
+module OrderItem = {
+  [@react.component]
+  let make = (~item: Item.t) =>
+    <tr>
+      <td> {item |> Item.toEmoji |> React.string} </td>
+      <td> {item |> Item.toPrice |> Format.currency} </td>
+    </tr>;
+};
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items
+       |> Js.Array.mapi((item, index) =>
+            <OrderItem key={"item-" ++ string_of_int(index)} item />
+          )
+       |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td> {total |> Format.currency} </td>
+      </tr>
+    </tbody>
+  </table>;
+};
type t = array(Item.t);
+
+module OrderItem = {
+  [@react.component]
+  let make = (~item: Item.t) =>
+    <tr>
+      <td> {item |> Item.toEmoji |> React.string} </td>
+      <td> {item |> Item.toPrice |> Format.currency} </td>
+    </tr>;
+};
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items
+       |> Js.Array.mapi((item, index) =>
+            <OrderItem key={"item-" ++ string_of_int(index)} item />
+          )
+       |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td> {total |> Format.currency} </td>
+      </tr>
+    </tbody>
+  </table>;
+};

2. After you add a HotDog constructor to Item.t, your Item module should look something like this:

re
type t =
+  | Sandwich
+  | Burger
+  | Hotdog;
+
+let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.
+  | Hotdog => 5.;
+
+let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js}
+  | Hotdog => {js|🌭|js};
type t =
+  | Sandwich
+  | Burger
+  | Hotdog;
+
+let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.
+  | Hotdog => 5.;
+
+let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js}
+  | Hotdog => {js|🌭|js};

Of course, you may have chosen a different price for the hotdog. Or maybe you didn’t add a hotdog at all, and instead added CannedFood (🥫) or PotOfFood (🍲). It’s totally up to you!

3. In order to create a helper function Format.currency, we must create a new module file called Format.re and add a currency function:

re
let currency = value =>
+  value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string;
let currency = value =>
+  value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string;

Then we can use that function like this:

reason
<td> {item |> toPrice |> Format.currency} </td>
<td> {item |> toPrice |> Format.currency} </td>

Source code for this chapter can be found in the Melange for React Developers repo.


  1. Variant types have no equivalent in JavaScript, but they are similar to TypeScript’s union enums ↩︎

  2. Recall that the name of this restaurant is Emoji Cafe, so everything from the menu to the order confirmation must use emojis. ↩︎

  3. All lowercase elements like div, span, table, etc expect their children to be of type React.element. But React components (with uppercase names) can take children of any type. ↩︎

  4. Using array indexes to set keys violates React’s rules of keys, which states that you shouldn’t generate keys while rendering. We’ll see a better way to do this later. ↩︎

  5. Madame Jellobutter was passing by and just happened to catch a glimpse of the unstyled component over your shoulder and puked in her mouth a little. ↩︎

`,84),e=[p];function t(c,r,y,E,i,d){return a(),n("div",null,e)}const D=s(o,[["render",t]]);export{B as __pageData,D as default}; diff --git a/assets/order-confirmation_index.md.c17c7e32.lean.js b/assets/order-confirmation_index.md.c17c7e32.lean.js new file mode 100644 index 00000000..b49c3f65 --- /dev/null +++ b/assets/order-confirmation_index.md.c17c7e32.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,Q as l}from"./chunks/framework.0e8ae64e.js";const B=JSON.parse('{"title":"Order Confirmation","description":"","frontmatter":{},"headers":[],"relativePath":"order-confirmation/index.md","filePath":"order-confirmation/index.md"}'),o={name:"order-confirmation/index.md"},p=l("",84),e=[p];function t(c,r,y,E,i,d){return a(),n("div",null,e)}const D=s(o,[["render",t]]);export{B as __pageData,D as default}; diff --git a/assets/style.a3f53c04.css b/assets/style.a3f53c04.css new file mode 100644 index 00000000..4ba860c0 --- /dev/null +++ b/assets/style.a3f53c04.css @@ -0,0 +1 @@ +@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic.5f2c6c8c.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic-ext.e75737ce.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek.d5a6d92a.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek-ext.ab0619bc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin.2ed14f66.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin-ext.0030eebd.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-vietnamese.14ce25a6.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic.ea42a392.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek.8f4463c4.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek-ext.4fbe9427.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin.bd3b6f56.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin-ext.bd8920cc.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-vietnamese.6ce511fb.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-green-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-green-1);--vp-code-line-diff-remove-color: var(--vp-c-red-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-red-1);--vp-code-line-warning-color: var(--vp-c-yellow-soft);--vp-code-line-error-color: var(--vp-c-red-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-brand-soft);--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-gray-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-brand-1);--vp-badge-tip-bg: var(--vp-c-brand-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);direction:ltr;font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{margin:auto}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-brand-1)}.custom-block.tip a:hover{color:var(--vp-c-brand-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code-light{display:none}html:not(.dark) .vp-code-dark{display:none}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge[data-v-ea5b2908]{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.vp-doc h1>.VPBadge[data-v-ea5b2908]{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge[data-v-ea5b2908]{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge[data-v-ea5b2908]{vertical-align:middle}.vp-doc h4>.VPBadge[data-v-ea5b2908],.vp-doc h5>.VPBadge[data-v-ea5b2908],.vp-doc h6>.VPBadge[data-v-ea5b2908]{vertical-align:middle;line-height:18px}.VPBadge.info[data-v-ea5b2908]{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip[data-v-ea5b2908]{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning[data-v-ea5b2908]{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger[data-v-ea5b2908]{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-54a304ca]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-54a304ca],.VPBackdrop.fade-leave-to[data-v-54a304ca]{opacity:0}.VPBackdrop.fade-leave-active[data-v-54a304ca]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-54a304ca]{display:none}}.NotFound[data-v-b9c0c15a]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-b9c0c15a]{padding:96px 32px 168px}}.code[data-v-b9c0c15a]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-b9c0c15a]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-b9c0c15a]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-b9c0c15a]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-b9c0c15a]{padding-top:20px}.link[data-v-b9c0c15a]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-b9c0c15a]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-463da30f]{position:relative;z-index:1}.nested[data-v-463da30f]{padding-left:16px}.outline-link[data-v-463da30f]{display:block;line-height:28px;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s;font-weight:400}.outline-link[data-v-463da30f]:hover,.outline-link.active[data-v-463da30f]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-463da30f]{padding-left:13px}.VPDocAsideOutline[data-v-3a6c4994]{display:none}.VPDocAsideOutline.has-outline[data-v-3a6c4994]{display:block}.content[data-v-3a6c4994]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-3a6c4994]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-3a6c4994]{letter-spacing:.4px;line-height:28px;font-size:13px;font-weight:600}.VPDocAside[data-v-cb998dce]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-cb998dce]{flex-grow:1}.VPDocAside[data-v-cb998dce] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-cb998dce] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-cb998dce] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-19a7ae4e]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-19a7ae4e]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-a2d931e4]{margin-top:64px}.edit-info[data-v-a2d931e4]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-a2d931e4]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-a2d931e4]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-a2d931e4]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-a2d931e4]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-a2d931e4]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-a2d931e4]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-a2d931e4]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-a2d931e4]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-a2d931e4]{margin-left:auto;text-align:right}.desc[data-v-a2d931e4]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-a2d931e4]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDocOutlineDropdown[data-v-95bb0785]{margin-bottom:48px}.VPDocOutlineDropdown button[data-v-95bb0785]{display:block;font-size:14px;font-weight:500;line-height:24px;border:1px solid var(--vp-c-border);padding:4px 12px;color:var(--vp-c-text-2);background-color:var(--vp-c-default-soft);border-radius:8px;transition:color .5s}.VPDocOutlineDropdown button[data-v-95bb0785]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPDocOutlineDropdown button.open[data-v-95bb0785]{color:var(--vp-c-text-1)}.icon[data-v-95bb0785]{display:inline-block;vertical-align:middle;width:16px;height:16px;fill:currentColor}[data-v-95bb0785] .outline-link{font-size:14px;font-weight:400}.open>.icon[data-v-95bb0785]{transform:rotate(90deg)}.items[data-v-95bb0785]{margin-top:12px;border-left:1px solid var(--vp-c-divider)}.VPDoc[data-v-a3c25e27]{padding:32px 24px 96px;width:100%}.VPDoc .VPDocOutlineDropdown[data-v-a3c25e27]{display:none}@media (min-width: 960px) and (max-width: 1279px){.VPDoc .VPDocOutlineDropdown[data-v-a3c25e27]{display:block}}@media (min-width: 768px){.VPDoc[data-v-a3c25e27]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-a3c25e27]{padding:32px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-a3c25e27]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-a3c25e27]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-a3c25e27]{display:flex;justify-content:center}.VPDoc .aside[data-v-a3c25e27]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-a3c25e27]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-a3c25e27]{max-width:1104px}}.container[data-v-a3c25e27]{margin:0 auto;width:100%}.aside[data-v-a3c25e27]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-a3c25e27]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-a3c25e27]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-a3c25e27]::-webkit-scrollbar{display:none}.aside-curtain[data-v-a3c25e27]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-a3c25e27]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px));padding-bottom:32px}.content[data-v-a3c25e27]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-a3c25e27]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-a3c25e27]{order:1;margin:0;min-width:640px}}.content-container[data-v-a3c25e27]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-a3c25e27]{max-width:688px}.external-link-icon-enabled[data-v-a3c25e27] :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.VPButton[data-v-1e76fe75]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-1e76fe75]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-1e76fe75]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-1e76fe75]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-1e76fe75]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-1e76fe75]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-1e76fe75]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-1e76fe75]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-1e76fe75]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-1e76fe75]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-1e76fe75]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-1e76fe75]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-1e76fe75]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-ab19afbb]{display:none}.dark .VPImage.light[data-v-ab19afbb]{display:none}.VPHero[data-v-5a3e9999]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-5a3e9999]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-5a3e9999]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-5a3e9999]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-5a3e9999]{flex-direction:row}}.main[data-v-5a3e9999]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-5a3e9999]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-5a3e9999]{text-align:left}}@media (min-width: 960px){.main[data-v-5a3e9999]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-5a3e9999]{max-width:592px}}.name[data-v-5a3e9999],.text[data-v-5a3e9999]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-5a3e9999],.VPHero.has-image .text[data-v-5a3e9999]{margin:0 auto}.name[data-v-5a3e9999]{color:var(--vp-home-hero-name-color)}.clip[data-v-5a3e9999]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-5a3e9999],.text[data-v-5a3e9999]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-5a3e9999],.text[data-v-5a3e9999]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-5a3e9999],.VPHero.has-image .text[data-v-5a3e9999]{margin:0}}.tagline[data-v-5a3e9999]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-5a3e9999]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-5a3e9999]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-5a3e9999]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-5a3e9999]{margin:0}}.actions[data-v-5a3e9999]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-5a3e9999]{justify-content:center}@media (min-width: 640px){.actions[data-v-5a3e9999]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-5a3e9999]{justify-content:flex-start}}.action[data-v-5a3e9999]{flex-shrink:0;padding:6px}.image[data-v-5a3e9999]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-5a3e9999]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-5a3e9999]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-5a3e9999]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-5a3e9999]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-5a3e9999]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-5a3e9999]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-5a3e9999]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-5a3e9999]{width:320px;height:320px}}[data-v-5a3e9999] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-5a3e9999] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-5a3e9999] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-ee984185]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-ee984185]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-ee984185]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-ee984185]>.VPImage{margin-bottom:20px}.icon[data-v-ee984185]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-ee984185]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-ee984185]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-ee984185]{padding-top:8px}.link-text-value[data-v-ee984185]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-ee984185]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-b1eea84a]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-b1eea84a]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-b1eea84a]{padding:0 64px}}.container[data-v-b1eea84a]{margin:0 auto;max-width:1152px}.items[data-v-b1eea84a]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-b1eea84a]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-b1eea84a],.item.grid-4[data-v-b1eea84a],.item.grid-6[data-v-b1eea84a]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-b1eea84a],.item.grid-4[data-v-b1eea84a]{width:50%}.item.grid-3[data-v-b1eea84a],.item.grid-6[data-v-b1eea84a]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-b1eea84a]{width:25%}}.VPHome[data-v-20eabd3a]{padding-bottom:96px}.VPHome[data-v-20eabd3a] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-20eabd3a]{padding-bottom:128px}}.VPContent[data-v-3cf691b6]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-3cf691b6]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-3cf691b6]{margin:0}@media (min-width: 960px){.VPContent[data-v-3cf691b6]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-3cf691b6]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-3cf691b6]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e4279f1c]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e4279f1c]{display:none}@media (min-width: 768px){.VPFooter[data-v-e4279f1c]{padding:32px}}.container[data-v-e4279f1c]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e4279f1c],.copyright[data-v-e4279f1c]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-24251f6f]{padding:12px 20px 11px}.VPLocalNavOutlineDropdown button[data-v-24251f6f]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-24251f6f]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-24251f6f]{color:var(--vp-c-text-1)}.icon[data-v-24251f6f]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-24251f6f] .outline-link{font-size:14px;padding:2px 0}.open>.icon[data-v-24251f6f]{transform:rotate(90deg)}.items[data-v-24251f6f]{position:absolute;top:64px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}.header[data-v-24251f6f]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-24251f6f]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-24251f6f]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-24251f6f]{transition:all .2s ease-out}.flyout-leave-active[data-v-24251f6f]{transition:all .15s ease-in}.flyout-enter-from[data-v-24251f6f],.flyout-leave-to[data-v-24251f6f]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-9e669cc1]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--vp-c-gutter);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-9e669cc1]{position:fixed}.VPLocalNav.reached-top[data-v-9e669cc1]{border-top-color:transparent}@media (min-width: 960px){.VPLocalNav[data-v-9e669cc1]{display:none}}.menu[data-v-9e669cc1]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-9e669cc1]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-9e669cc1]{padding:0 32px}}.menu-icon[data-v-9e669cc1]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-9e669cc1]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-9e669cc1]{padding:12px 32px 11px}}.VPSwitch[data-v-1c29e291]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-1c29e291]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-1c29e291]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-1c29e291]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-1c29e291] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-1c29e291] svg{fill:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-3329432d]{opacity:1}.moon[data-v-3329432d],.dark .sun[data-v-3329432d]{opacity:0}.dark .moon[data-v-3329432d]{opacity:1}.dark .VPSwitchAppearance[data-v-3329432d] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-283b26e9]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-283b26e9]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-f51f088d]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-f51f088d]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-f51f088d]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-f51f088d]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-a6b0397c]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-a6b0397c]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-a6b0397c]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-a6b0397c]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-e42ed9b3]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-e42ed9b3] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-e42ed9b3] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-e42ed9b3] .group:last-child{padding-bottom:0}.VPMenu[data-v-e42ed9b3] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-e42ed9b3] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-e42ed9b3] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-e42ed9b3] .action{padding-left:24px}.VPFlyout[data-v-aa8de344]{position:relative}.VPFlyout[data-v-aa8de344]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-aa8de344]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-aa8de344]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-aa8de344]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-aa8de344]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-aa8de344],.button[aria-expanded=true]+.menu[data-v-aa8de344]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-aa8de344]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-aa8de344]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-aa8de344]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-aa8de344]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-aa8de344]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-aa8de344]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-aa8de344]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-16cf740a]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-16cf740a]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-16cf740a]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-e71e869c]{display:flex;justify-content:center}.VPNavBarExtra[data-v-c8c2ae4b]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-c8c2ae4b]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-c8c2ae4b]{display:none}}.trans-title[data-v-c8c2ae4b]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-c8c2ae4b],.item.social-links[data-v-c8c2ae4b]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-c8c2ae4b]{min-width:176px}.appearance-action[data-v-c8c2ae4b]{margin-right:-2px}.social-links-list[data-v-c8c2ae4b]{margin:-4px -8px}.VPNavBarHamburger[data-v-6bee1efd]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-6bee1efd]{display:none}}.container[data-v-6bee1efd]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-6bee1efd]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-6bee1efd]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-6bee1efd]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-6bee1efd]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-6bee1efd]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-6bee1efd]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-6bee1efd],.VPNavBarHamburger.active:hover .middle[data-v-6bee1efd],.VPNavBarHamburger.active:hover .bottom[data-v-6bee1efd]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-6bee1efd],.middle[data-v-6bee1efd],.bottom[data-v-6bee1efd]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-6bee1efd]{top:0;left:0;transform:translate(0)}.middle[data-v-6bee1efd]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-6bee1efd]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-cb318fec]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-cb318fec],.VPNavBarMenuLink[data-v-cb318fec]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-f732b5d0]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-f732b5d0]{display:flex}}/*! @docsearch/css 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-ef6192dc]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-ef6192dc]{display:flex;align-items:center}}.title[data-v-2973dbb4]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-2973dbb4]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-2973dbb4]{border-bottom-color:var(--vp-c-divider)}}[data-v-2973dbb4] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-ff4524ae]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-ff4524ae]{display:flex;align-items:center}}.title[data-v-ff4524ae]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-f1abbc6e]{position:relative;border-bottom:1px solid transparent;padding:0 8px 0 24px;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap}@media (min-width: 768px){.VPNavBar[data-v-f1abbc6e]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar[data-v-f1abbc6e]{padding:0}.VPNavBar[data-v-f1abbc6e]:not(.has-sidebar):not(.top){border-bottom-color:var(--vp-c-gutter);background-color:var(--vp-nav-bg-color)}}.container[data-v-f1abbc6e]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-f1abbc6e],.container>.content[data-v-f1abbc6e]{pointer-events:none}.container[data-v-f1abbc6e] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-f1abbc6e]{max-width:100%}}.title[data-v-f1abbc6e]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-f1abbc6e]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-f1abbc6e]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-f1abbc6e]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-f1abbc6e]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-f1abbc6e]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-f1abbc6e]{display:flex;justify-content:flex-end;align-items:center;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.top) .content-body[data-v-f1abbc6e]{position:relative;background-color:var(--vp-nav-bg-color)}}@media (max-width: 767px){.content-body[data-v-f1abbc6e]{column-gap:.5rem}}.menu+.translations[data-v-f1abbc6e]:before,.menu+.appearance[data-v-f1abbc6e]:before,.menu+.social-links[data-v-f1abbc6e]:before,.translations+.appearance[data-v-f1abbc6e]:before,.appearance+.social-links[data-v-f1abbc6e]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-f1abbc6e]:before,.translations+.appearance[data-v-f1abbc6e]:before{margin-right:16px}.appearance+.social-links[data-v-f1abbc6e]:before{margin-left:16px}.social-links[data-v-f1abbc6e]{margin-right:-8px}@media (min-width: 960px){.VPNavBar.has-sidebar .curtain[data-v-f1abbc6e]{position:absolute;right:0;bottom:-31px;width:calc(100% - var(--vp-sidebar-width));height:32px}.VPNavBar.has-sidebar .curtain[data-v-f1abbc6e]:before{display:block;width:100%;height:32px;background:linear-gradient(var(--vp-c-bg),transparent 70%);content:""}}@media (min-width: 1440px){.VPNavBar.has-sidebar .curtain[data-v-f1abbc6e]{width:calc(100% - ((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width)))}}.VPNavScreenAppearance[data-v-0dc5cf49]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-0dc5cf49]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-fe523e3d]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-fe523e3d]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-aea78dd1]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-aea78dd1]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-f60dbfa7]{display:block}.title[data-v-f60dbfa7]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-c2c554ed]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-c2c554ed]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-c2c554ed]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-c2c554ed]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-c2c554ed]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-c2c554ed]{transform:rotate(45deg)}.button[data-v-c2c554ed]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-c2c554ed]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-c2c554ed]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-c2c554ed]:first-child{padding-top:0}.group+.group[data-v-c2c554ed],.group+.item[data-v-c2c554ed]{padding-top:4px}.VPNavScreenTranslations[data-v-41505286]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-41505286]{height:auto}.title[data-v-41505286]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-41505286]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-41505286]{margin-right:8px}.icon.chevron[data-v-41505286]{margin-left:4px}.list[data-v-41505286]{padding:4px 0 0 24px}.link[data-v-41505286]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-57cce842]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-57cce842],.VPNavScreen.fade-leave-active[data-v-57cce842]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-57cce842],.VPNavScreen.fade-leave-active .container[data-v-57cce842]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-57cce842],.VPNavScreen.fade-leave-to[data-v-57cce842]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-57cce842],.VPNavScreen.fade-leave-to .container[data-v-57cce842]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-57cce842]{display:none}}.container[data-v-57cce842]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-57cce842],.menu+.appearance[data-v-57cce842],.translations+.appearance[data-v-57cce842]{margin-top:24px}.menu+.social-links[data-v-57cce842]{margin-top:16px}.appearance+.social-links[data-v-57cce842]{margin-top:16px}.VPNav[data-v-7ad780c2]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-7ad780c2]{position:fixed}}.VPSidebarItem.level-0[data-v-bd01e0d5]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-bd01e0d5]{padding-bottom:10px}.item[data-v-bd01e0d5]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-bd01e0d5]{cursor:pointer}.indicator[data-v-bd01e0d5]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-bd01e0d5],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-bd01e0d5],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-bd01e0d5],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-bd01e0d5]{background-color:var(--vp-c-brand-1)}.link[data-v-bd01e0d5]{display:flex;align-items:center;flex-grow:1}.text[data-v-bd01e0d5]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-bd01e0d5]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-bd01e0d5],.VPSidebarItem.level-2 .text[data-v-bd01e0d5],.VPSidebarItem.level-3 .text[data-v-bd01e0d5],.VPSidebarItem.level-4 .text[data-v-bd01e0d5],.VPSidebarItem.level-5 .text[data-v-bd01e0d5]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-bd01e0d5],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-bd01e0d5],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-bd01e0d5],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-bd01e0d5],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-bd01e0d5],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-bd01e0d5]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-1.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-2.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-3.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-4.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-5.has-active>.item>.text[data-v-bd01e0d5],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-bd01e0d5],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-bd01e0d5],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-bd01e0d5],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-bd01e0d5],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-bd01e0d5],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-bd01e0d5]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-bd01e0d5],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-bd01e0d5],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-bd01e0d5],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-bd01e0d5],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-bd01e0d5],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-bd01e0d5]{color:var(--vp-c-brand-1)}.caret[data-v-bd01e0d5]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-bd01e0d5]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-bd01e0d5]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-bd01e0d5]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-bd01e0d5]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-bd01e0d5],.VPSidebarItem.level-2 .items[data-v-bd01e0d5],.VPSidebarItem.level-3 .items[data-v-bd01e0d5],.VPSidebarItem.level-4 .items[data-v-bd01e0d5],.VPSidebarItem.level-5 .items[data-v-bd01e0d5]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-bd01e0d5]{display:none}.VPSidebar[data-v-ee2efba5]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-ee2efba5]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-ee2efba5]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-ee2efba5]{z-index:1;padding-top:var(--vp-nav-height);padding-bottom:128px;width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-ee2efba5]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-ee2efba5]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-ee2efba5]{outline:0}.group+.group[data-v-ee2efba5]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-ee2efba5]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-c8291ffa]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-c8291ffa]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-c8291ffa]{top:14px;left:16px}}.Layout[data-v-9d8abc1e]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-843cc1b2]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-843cc1b2]{margin:0 auto;max-width:1152px}.love[data-v-843cc1b2]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-843cc1b2]{width:28px;height:28px;fill:currentColor}.message[data-v-843cc1b2]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-843cc1b2]{padding-top:32px}.action[data-v-843cc1b2]{padding-top:40px;text-align:center}.VPTeamPage[data-v-b1cfd8dc]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-b1cfd8dc]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-b1cfd8dc-s],.VPTeamMembers+.VPTeamPageSection[data-v-b1cfd8dc-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-b1cfd8dc-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-b1cfd8dc-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-b1cfd8dc-s],.VPTeamMembers+.VPTeamPageSection[data-v-b1cfd8dc-s]{margin-top:96px}}.VPTeamMembers[data-v-b1cfd8dc-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-b1cfd8dc-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-b1cfd8dc-s]{padding:0 64px}}.VPTeamPageTitle[data-v-46c5e327]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-46c5e327]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-46c5e327]{padding:80px 64px 48px}}.title[data-v-46c5e327]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-46c5e327]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-46c5e327]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-46c5e327]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-3bf2e850]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-3bf2e850]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-3bf2e850]{padding:0 64px}}.title[data-v-3bf2e850]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-3bf2e850]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-3bf2e850]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-3bf2e850]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-3bf2e850]{padding-top:40px}.VPTeamMembersItem[data-v-3a0078bd]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-3a0078bd]{padding:32px}.VPTeamMembersItem.small .data[data-v-3a0078bd]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-3a0078bd]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-3a0078bd]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-3a0078bd]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-3a0078bd]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-3a0078bd]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-3a0078bd]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-3a0078bd]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-3a0078bd]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-3a0078bd]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-3a0078bd]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-3a0078bd]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-3a0078bd]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-3a0078bd]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-3a0078bd]{text-align:center}.avatar[data-v-3a0078bd]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-3a0078bd]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-3a0078bd]{margin:0;font-weight:600}.affiliation[data-v-3a0078bd]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-3a0078bd]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-3a0078bd]:hover{color:var(--vp-c-brand-1)}.desc[data-v-3a0078bd]{margin:0 auto}.desc[data-v-3a0078bd] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-3a0078bd]{display:flex;justify-content:center;height:56px}.sp-link[data-v-3a0078bd]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-3a0078bd]:hover,.sp .sp-link.link[data-v-3a0078bd]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-3a0078bd]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-bf782009]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-bf782009]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-bf782009]{max-width:876px}.VPTeamMembers.medium .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-bf782009]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-bf782009]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-bf782009]{max-width:760px}.container[data-v-bf782009]{display:grid;gap:24px;margin:0 auto;max-width:1152px}.VPLocalSearchBox[data-v-2813d7e3]{position:fixed;z-index:100;top:0;right:0;bottom:0;left:0;display:flex}.backdrop[data-v-2813d7e3]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-2813d7e3]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media (max-width: 767px){.shell[data-v-2813d7e3]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-2813d7e3]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media (max-width: 767px){.search-bar[data-v-2813d7e3]{padding:0 8px}}.search-bar[data-v-2813d7e3]:focus-within{border-color:var(--vp-c-brand-1)}.search-icon[data-v-2813d7e3]{margin:8px}@media (max-width: 767px){.search-icon[data-v-2813d7e3]{display:none}}.search-input[data-v-2813d7e3]{padding:6px 12px;font-size:inherit;width:100%}@media (max-width: 767px){.search-input[data-v-2813d7e3]{padding:6px 4px}}.search-actions[data-v-2813d7e3]{display:flex;gap:4px}@media (any-pointer: coarse){.search-actions[data-v-2813d7e3]{gap:8px}}@media (min-width: 769px){.search-actions.before[data-v-2813d7e3]{display:none}}.search-actions button[data-v-2813d7e3]{padding:8px}.search-actions button[data-v-2813d7e3]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-2813d7e3]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-2813d7e3]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-2813d7e3]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-2813d7e3]{display:flex;align-items:center;gap:4px}@media (max-width: 767px){.search-keyboard-shortcuts[data-v-2813d7e3]{display:none}}.search-keyboard-shortcuts kbd[data-v-2813d7e3]{background:rgba(128,128,128,.1);border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-2813d7e3]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-2813d7e3]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-2813d7e3]{margin:12px;width:100%;overflow:hidden}@media (max-width: 767px){.result>div[data-v-2813d7e3]{margin:8px}}.titles[data-v-2813d7e3]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-2813d7e3]{display:flex;align-items:center;gap:4px}.title.main[data-v-2813d7e3]{font-weight:500}.title-icon[data-v-2813d7e3]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-2813d7e3]{opacity:.5}.result.selected[data-v-2813d7e3]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-2813d7e3]{position:relative}.excerpt[data-v-2813d7e3]{opacity:75%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;opacity:.5;margin-top:4px}.result.selected .excerpt[data-v-2813d7e3]{opacity:1}.excerpt[data-v-2813d7e3] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-2813d7e3] mark,.excerpt[data-v-2813d7e3] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-2813d7e3] .vp-code-group .tabs{display:none}.excerpt[data-v-2813d7e3] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-2813d7e3]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-2813d7e3]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-2813d7e3],.result.selected .title-icon[data-v-2813d7e3]{color:var(--vp-c-brand-1)!important}.no-results[data-v-2813d7e3]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-2813d7e3]{flex:none} diff --git a/assets/todo.md.6e486e47.js b/assets/todo.md.6e486e47.js new file mode 100644 index 00000000..9046fba8 --- /dev/null +++ b/assets/todo.md.6e486e47.js @@ -0,0 +1 @@ +import{_ as t,o,c as a,k as e,a as n}from"./chunks/framework.0e8ae64e.js";const k=JSON.parse('{"title":"Content not yet unavailable","description":"","frontmatter":{"layout":"doc","prev":false,"next":false},"headers":[],"relativePath":"todo.md","filePath":"todo.md"}'),c={name:"todo.md"},l=e("h1",{id:"content-not-yet-unavailable",tabindex:"-1"},[n("Content not yet unavailable "),e("a",{class:"header-anchor",href:"#content-not-yet-unavailable","aria-label":'Permalink to "Content not yet unavailable"'},"​")],-1),s=e("p",null,"We are hard at work writing the content you requested. Please check back later.",-1),r=e("blockquote",null,[e("p",null,"Docendo disco, scribendo cogito")],-1),d=[l,s,r];function i(_,u,h,p,f,b){return o(),a("div",null,d)}const v=t(c,[["render",i]]);export{k as __pageData,v as default}; diff --git a/assets/todo.md.6e486e47.lean.js b/assets/todo.md.6e486e47.lean.js new file mode 100644 index 00000000..9046fba8 --- /dev/null +++ b/assets/todo.md.6e486e47.lean.js @@ -0,0 +1 @@ +import{_ as t,o,c as a,k as e,a as n}from"./chunks/framework.0e8ae64e.js";const k=JSON.parse('{"title":"Content not yet unavailable","description":"","frontmatter":{"layout":"doc","prev":false,"next":false},"headers":[],"relativePath":"todo.md","filePath":"todo.md"}'),c={name:"todo.md"},l=e("h1",{id:"content-not-yet-unavailable",tabindex:"-1"},[n("Content not yet unavailable "),e("a",{class:"header-anchor",href:"#content-not-yet-unavailable","aria-label":'Permalink to "Content not yet unavailable"'},"​")],-1),s=e("p",null,"We are hard at work writing the content you requested. Please check back later.",-1),r=e("blockquote",null,[e("p",null,"Docendo disco, scribendo cogito")],-1),d=[l,s,r];function i(_,u,h,p,f,b){return o(),a("div",null,d)}const v=t(c,[["render",i]]);export{k as __pageData,v as default}; diff --git a/celsius-converter-exception/index.html b/celsius-converter-exception/index.html new file mode 100644 index 00000000..9080b72d --- /dev/null +++ b/celsius-converter-exception/index.html @@ -0,0 +1,311 @@ + + + + + + Celsius Converter | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Celsius Converter

Our second widget will be one that takes a temperature value in Celsius and converts it to Fahrenheit. Create a new file called CelsiusConverter.re:

re
let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = ReactEvent.Form.target(evt)##value;
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};
let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = ReactEvent.Form.target(evt)##value;
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};

Inside the input’s onChange handler, we get the event target using ReactEvent.Form.target, which has the type ReactEvent.Form.t => {_.. }. What is {_.. }? It’s shorthand for the Js.t({..}) type[1], which consists of two parts:

  • Js.t refers to JavaScript objects in Melange
  • {..} refers to polymorphic objects which can contain any fields or methods

Once we have a Js.t object, we can use the ## operator to access its fields. But beware, because the compiler knows nothing about the types of those fields. For example, we could write ReactEvent.Form.target(evt)##value + 1, treating it as if it were an integer, and the compiler wouldn’t complain.

Wrap functions that return Js.t

Instead of trusting ourselves to always use ReactEvent.Form.target(evt)##value correctly, it’s a good idea to wrap functions that return polymorphic objects into type-annotated helper functions. For example:

re
let getValueFromEvent = (evt): string =>
+  ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};
let getValueFromEvent = (evt): string =>
+  ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {React.string({js|?°F|js})}
+  </div>;
+};

The : string after the argument list tells the compiler that this function must return a string. Using the getValueFromEvent function ensures that the value field can’t be used as anything other than a string.

Another thing to note about onChange is that after the evt argument, the body of the callback function is surrounded by braces ({}). OCaml functions are like JavaScript’s arrow functions—if they contain more than one line, they need to be enclosed by braces.

Apply pipe last (|>)

Let’s change the render logic to update the Fahrenheit display based on the value of celsius:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {celsius |> float_of_string |> convert |> string_of_float |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {celsius |> float_of_string |> convert |> string_of_float |> React.string}
+</div>;

The pipe last operator (|>) is very handy here, allowing us to convert a string to float, then convert that float to another float (Celsius -> Fahrenheit), convert back to string, and finally convert the string to React.element, all in one line.

String concatenation (++)

We should probably put °F after the Fahrenheit value so that it’s clear to the user what unit of measure they’re seeing. We can do so using the string concatenation operator (++):

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(celsius |> float_of_string |> convert |> string_of_float)
+   ++ {js|°F|js}
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(celsius |> float_of_string |> convert |> string_of_float)
+   ++ {js|°F|js}
+   |> React.string}
+</div>;

Catch exception with switch

However, there’s a bug in this code: it will crash if you enter anything into the input that can’t be converted to a float. We can remedy this by catching the exception using a switch expression:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception _ => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception _ => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;

The | exception _ branch will execute if there is any exception. The underscore (_) is a wildcard, meaning it will match any exception. If we wanted to be specific about which exception we want to catch, we could instead write

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception (Failure(_)) => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     switch (celsius |> float_of_string |> convert |> string_of_float) {
+     | exception (Failure(_)) => "error"
+     | fahrenheit => fahrenheit ++ {js|°F|js}
+     }
+   )
+   |> React.string}
+</div>;

Ternary expression

Right now it correctly renders “error” when you enter an invalid value, but it also renders “error” if the input is blank. It might be bit more user-friendly to instead show “?°F” like before. We can do that by wrapping the switch expression in a ternary expression:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert |> string_of_float) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert |> string_of_float) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

If-else expression

The ternary expression (condition ? a : b) works the same as in JavaScript. But in OCaml, it’s also shorthand for an if-else expression (if (condition) { a; } else { b; }). So we could rewrite it as this:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     if (celsius == "") {
+       {js|?°F|js};
+     } else {
+       switch (celsius |> float_of_string |> convert |> string_of_float) {
+       | exception _ => "error"
+       | fahrenheit => fahrenheit ++ {js|°F|js}
+       };
+     }
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     if (celsius == "") {
+       {js|?°F|js};
+     } else {
+       switch (celsius |> float_of_string |> convert |> string_of_float) {
+       | exception _ => "error"
+       | fahrenheit => fahrenheit ++ {js|°F|js}
+       };
+     }
+   )
+   |> React.string}
+</div>;

Unlike in JavaScript, the if-else construct is an expression and always yields a value. Both branches must return a value of the same type or you’ll get a compilation error. In practice, if-else expressions aren’t very common in OCaml code because in simple cases you can use ternary, and in more complex cases you can use switch. But it’s a nice, familiar fallback you can rely on when you haven’t quite gotten used to OCaml syntax yet.

Labeled argument

If we enter a value with a lot of decimals in it, e.g. 21.1223456, we’ll get a Fahrenheit value with a lot of decimals in it as well. We can limit the number of decimals in the converted value using Js.Float.toFixedWithPrecision:

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert) {
+         | exception _ => "error"
+         | fahrenheit =>
+           Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2)
+           ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (celsius |> float_of_string |> convert) {
+         | exception _ => "error"
+         | fahrenheit =>
+           Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2)
+           ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

Js.Float.toFixedWithPrecision is a function that has one positional argument and one labeled argument. In this case, the labeled argument is named digits and it’s receiving a value of 2. It’s not possible to pass in the value of a labeled argument without using the ~label=value syntax. We’ll see more of labeled arguments in the following chapters when we introduce props.

Partial application

You might have noticed that the function chain feeding the switch expression got a bit shorter, from

reason
celsius |> float_of_string |> convert |> string_of_float
celsius |> float_of_string |> convert |> string_of_float

to

reason
celsius |> float_of_string |> convert
celsius |> float_of_string |> convert

This happened because string_of_float, which takes a single argument, was replaced by Js.Float.toFixedWithPrecision, which takes two arguments, and functions chained using |> can only take a single argument. But this one-argument restriction actually doesn’t prevent us from putting Js.Float.toFixedWithPrecision in the chain! We can take advantage of OCaml’s partial application feature to create a one-argument function by writing Js.Float.toFixedWithPrecision(~digits=2). Then our switch expression becomes

re
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (
+           celsius
+           |> float_of_string
+           |> convert
+           |> Js.Float.toFixedWithPrecision(~digits=2)
+         ) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;
<div>
+  <input /* ... */ />
+  {React.string({js|°C = |js})}
+  {(
+     celsius == ""
+       ? {js|?°F|js}
+       : (
+         switch (
+           celsius
+           |> float_of_string
+           |> convert
+           |> Js.Float.toFixedWithPrecision(~digits=2)
+         ) {
+         | exception _ => "error"
+         | fahrenheit => fahrenheit ++ {js|°F|js}
+         }
+       )
+   )
+   |> React.string}
+</div>;

We have a working component now, but catching exceptions isn’t The OCaml Way! In the next chapter, you’ll see how to rewrite the logic using option.

Exercises

1. Try changing {js|°C = |js} to "°C = ". What happens?

2. It’s possible to rewrite the onChange callback so that it contains a single expression:

re
<input
+  value=celsius
+  onChange={evt => setCelsius(_ => getValueFromEvent(evt))}
+/>;
<input
+  value=celsius
+  onChange={evt => setCelsius(_ => getValueFromEvent(evt))}
+/>;

This compiles, but it now contains a hidden bug. Do you know what silent error might occur?

3. It’s possible to use partial application with most functions in OCaml, even operators. Take a look at the following program:

reason
let addFive = (+)(5);
+Js.log(addFive(2));
+Js.log(addFive(7));
+Js.log(addFive(10));
let addFive = (+)(5);
+Js.log(addFive(2));
+Js.log(addFive(7));
+Js.log(addFive(10));

What do you think it outputs? Run it in Melange Playground to confirm your hypothesis.

4. Use the pipe last operator (|>) and partial application to write a function that takes an integer argument x, subtracts x from 10, and converts that result to binary. Hint: Use the Js.Int.toStringWithRadix function.

Overview

  • Js.t objects (with the type Js.t({..})) can have fields of any name and type.
    • You access fields of a Js.t object using the ## operator.
    • You can use type annotations to make the use of such objects safer.
  • Concatenate strings using the ++ operator.
  • Switch expressions can be used to catch exceptions.
  • Ternary expressions have the same syntax as in JS. Unlike in JS, they are also shorthand for if-else expressions.
  • The two branches of if-else expressions must return values of the same type.
  • Besides positional arguments, OCaml functions can also have labeled arguments.
  • If a function takes two arguments, we can supply one of them and get a function that takes only one argument. This is called partial application.

Solutions

1. Changing it to "°C = " will result in a bit of gibberish being rendered: “°C”. We can’t rely on OCaml strings to deal with Unicode correctly, so any string that contains non-ASCII text must be delimited using {js||js}.

TIP

Note that quoted string literals using the js identifier are specific to Melange and are not available in native OCaml.

2. Rewriting onChange the handler to use a single expression creates a potential problem with stale values coming from the event object:

re
<input
+  value=celsius
+  onChange={evt =>
+    setCelsius(_ => {
+      // we are no longer in the scope of onChange
+      getValueFromEvent(evt)
+    })
+  }
+/>;
<input
+  value=celsius
+  onChange={evt =>
+    setCelsius(_ => {
+      // we are no longer in the scope of onChange
+      getValueFromEvent(evt)
+    })
+  }
+/>;

Inside of onChange, we can expect the function getValueFromEvent(evt) to return the latest value of the input. However, we are now calling getValueFromEvent(evt) from a different function—the callback we pass to setCelsius! By the time that setCelsius’s callback is invoked, the evt object might have been recycled and no longer have the same value as when onChange was initially invoked. For more details about this, see Using Event Values with useState in the ReasonReact docs.

3. Playground: Define an addFive function using partial application

4. Playground: Define a function that subtracts from 10 and converts to binary


Source code for this chapter can be found in the Melange for React Developers repo.


  1. See Using Js.t objects for more details. ↩︎

+ + + + \ No newline at end of file diff --git a/celsius-converter-option/index.html b/celsius-converter-option/index.html new file mode 100644 index 00000000..7a71a827 --- /dev/null +++ b/celsius-converter-option/index.html @@ -0,0 +1,261 @@ + + + + + + Celsius Converter using Option | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Celsius Converter using Option

After all the changes we made in the last chapter, your CelsiusConverter.re might look something like this:

re
let getValueFromEvent = (evt): string => ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {(
+       celsius == ""
+         ? {js|?°F|js}
+         : (
+           switch (
+             celsius
+             |> float_of_string
+             |> convert
+             |> Js.Float.toFixedWithPrecision(~digits=2)
+           ) {
+           | exception _ => "error"
+           | fahrenheit => fahrenheit ++ {js|°F|js}
+           }
+         )
+     )
+     |> React.string}
+  </div>;
+};
let getValueFromEvent = (evt): string => ReactEvent.Form.target(evt)##value;
+
+let convert = celsius => 9.0 /. 5.0 *. celsius +. 32.0;
+
+[@react.component]
+let make = () => {
+  let (celsius, setCelsius) = React.useState(() => "");
+
+  <div>
+    <input
+      value=celsius
+      onChange={evt => {
+        let newCelsius = getValueFromEvent(evt);
+        setCelsius(_ => newCelsius);
+      }}
+    />
+    {React.string({js|°C = |js})}
+    {(
+       celsius == ""
+         ? {js|?°F|js}
+         : (
+           switch (
+             celsius
+             |> float_of_string
+             |> convert
+             |> Js.Float.toFixedWithPrecision(~digits=2)
+           ) {
+           | exception _ => "error"
+           | fahrenheit => fahrenheit ++ {js|°F|js}
+           }
+         )
+     )
+     |> React.string}
+  </div>;
+};

What happens if you forget the | exception _ branch of your switch expression? Your program will crash when invalid input is entered. The compiler won’t warn you to add an exception branch because it doesn’t keep track of which functions throw exceptions. Next, we’ll show you a better way which completely avoids functions that can fail in unexpected ways.

float_of_string_opt

Refactor the switch expression to use float_of_string_opt instead. This function has the type signature string => option(float). It takes a string argument and returns Some(number) if it succeeds and None if it fails—meaning that even if this function fails, no exception is raised.

re
(
+  switch (celsius |> float_of_string_opt) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    (fahrenheit |> convert |> Js.Float.toFixedWithPrecision(~digits=2))
+    ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    (fahrenheit |> convert |> Js.Float.toFixedWithPrecision(~digits=2))
+    ++ {js|°F|js}
+  }
+)

In terms of functionality, this does exactly what the previous version did. But a critical difference is that if you comment out the | None branch, the compiler will refuse to accept it:

File "CelsiusConverter.re", lines 21-32, characters 11-10:
+21 | ...........(
+22 |            switch (celsius |> float_of_string_opt) {
+23 |            //  | None => "error"
+24 |            | Some(fahrenheit) =>
+25 |              (
+...
+29 |              )
+30 |              ++ {js| °F|js}
+31 |            }
+32 |          )
+Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None
File "CelsiusConverter.re", lines 21-32, characters 11-10:
+21 | ...........(
+22 |            switch (celsius |> float_of_string_opt) {
+23 |            //  | None => "error"
+24 |            | Some(fahrenheit) =>
+25 |              (
+...
+29 |              )
+30 |              ++ {js| °F|js}
+31 |            }
+32 |          )
+Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None

You would get a similar error if you left off the | Some(_) branch. Having an option value be the input for a switch expression means that you can’t forget to handle the failure case, much less the success case. There’s another advantage: The | Some(fahrenheit) branch gives you access to the float that was successfully converted from the string, and only this branch has access to that value. So you can be reasonably sure that the success case is handled here and not somewhere else. You are starting to experience the power of pattern matching in OCaml.

Option.map

It’s a shame we had to give up the long chain of function calls from when we were still using float_of_string:

reason
celsius
+|> float_of_string
+|> convert
+|> Js.Float.toFixedWithPrecision(~digits=2)
celsius
+|> float_of_string
+|> convert
+|> Js.Float.toFixedWithPrecision(~digits=2)

Actually, we can still use a very similar chain of functions with float_of_string_opt if we make a couple of small additions:

reason
celsius
+|> float_of_string_opt
+|> Option.map(convert)
+|> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
celsius
+|> float_of_string_opt
+|> Option.map(convert)
+|> Option.map(Js.Float.toFixedWithPrecision(~digits=2))

Option.map takes a function and an option value, and only invokes the function if the option was Some(_). Hovering over it, you can see that its type signature is:

('a => 'b, option('a)) => option('b)
('a => 'b, option('a)) => option('b)

Breaking the type signature down:

  • The first argument, 'a => 'b, is function which accepts a value of type 'a (placeholder for any type) and returns a value of type 'b (also a placeholder for any type, though it may be a different type than 'a).
  • The second argument, option('a), is an option that wraps around a value of type 'a.
  • The return type of Option.map is option('b), which is an option that wraps around a value of type 'b.

The implementation of Option.map is fairly straightforward, consisting of a single switch expression:

reason
let map = (func, option) =>
+  switch (option) {
+  | None => None
+  | Some(v) => Some(func(v))
+  };
let map = (func, option) =>
+  switch (option) {
+  | None => None
+  | Some(v) => Some(func(v))
+  };

You may be interested in browsing the many other helper functions related to option in the standard library’s Option module.

At this point, your switch expression might look like this:

re
(
+  switch (
+    celsius
+    |> float_of_string_opt
+    |> Option.map(convert)
+    |> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
+  ) {
+  | None => "error"
+  | Some(fahrenheit) => fahrenheit ++ {js|°F|js}
+  }
+)
(
+  switch (
+    celsius
+    |> float_of_string_opt
+    |> Option.map(convert)
+    |> Option.map(Js.Float.toFixedWithPrecision(~digits=2))
+  ) {
+  | None => "error"
+  | Some(fahrenheit) => fahrenheit ++ {js|°F|js}
+  }
+)

when guard

What if we wanted to render a message of complaint when the temperature goes above 212° F (the boiling point of water) and not even bother to render the converted number? It could look like this:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    fahrenheit > 212.0
+      ? {js|Unreasonably hot🥵|js}
+      : Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) =>
+    fahrenheit > 212.0
+      ? {js|Unreasonably hot🥵|js}
+      : Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)

This works, but OCaml gives you a construct that allows you to do the float comparison without using a nested ternary expression:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+  }
+)

The when guard allows you to add extra conditions to a switch expression branch, keeping nesting of conditionals to a minimum and making your code more readable.

Hooray! Our Celsius converter is finally complete. Later, we’ll see how to create a component that can convert back and forth between Celsius and Fahrenheit. But first, we’ll explore Dune, the build system used by Melange.

Exercises

1. If you enter a space in the input, it’ll unintuitively produce a Fahrenheit value of 32.00 degrees (because float_of_string_opt(" ") == Some(0.)). Handle this case correctly by showing “? °F” instead. Hint: Use the String.trim function.

2. Add another branch with a when guard that renders “Unreasonably cold🥶” if the temperature is less than -128.6°F (the lowest temperature ever recorded on Earth).

3. Use Js.Float.fromString instead of float_of_string_opt to parse a string to float. Hint: Use Js.Float.isNaN.

Overview

  • Prefer functions that return option over those that throw exceptions.
    • When the input of a switch expression is option, the compiler can helpfully remind you to handle the error case.
  • Option.map is very useful when chaining functions that return option.
  • You can use a when guard to make your switch expression more expressive without nesting conditionals.

Solutions

1. To prevent a space from producing 32.00 degrees Fahrenheit, just add a call to String.trim in your render logic:

re
(
+  String.trim(celsius) == ""
+    ? {js|?°F|js}
+    : (
+      switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+      | None => "error"
+      | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+      | Some(fahrenheit) =>
+        Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+      }
+    )
+)
(
+  String.trim(celsius) == ""
+    ? {js|?°F|js}
+    : (
+      switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+      | None => "error"
+      | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+      | Some(fahrenheit) =>
+        Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js| °F|js}
+      }
+    )
+)

2. To render “Unreasonably cold” when the temperature is less than -128.6°F, you can add another Some(fahrenheit) branch with a when guard:

re
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> float_of_string_opt |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)

3. To use Js.Float.fromString instead of float_of_string_opt, you can define a new helper function that takes a string and returns option:

re
let floatFromString = text => {
+  let value = Js.Float.fromString(text);
+  Js.Float.isNaN(value) ? None : Some(value);
+};
let floatFromString = text => {
+  let value = Js.Float.fromString(text);
+  Js.Float.isNaN(value) ? None : Some(value);
+};

Then substitute float_of_string_opt with floatFromString in your switch expression:

re
(
+  switch (celsius |> floatFromString |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)
(
+  switch (celsius |> floatFromString |> Option.map(convert)) {
+  | None => "error"
+  | Some(fahrenheit) when fahrenheit < (-128.6) => {js|Unreasonably cold🥶|js}
+  | Some(fahrenheit) when fahrenheit > 212.0 => {js|Unreasonably hot🥵|js}
+  | Some(fahrenheit) =>
+    Js.Float.toFixedWithPrecision(fahrenheit, ~digits=2) ++ {js|°F|js}
+  }
+)

Source code for this chapter can be found in the Melange for React Developers repo.

+ + + + \ No newline at end of file diff --git a/counter/index.html b/counter/index.html new file mode 100644 index 00000000..3ea418a5 --- /dev/null +++ b/counter/index.html @@ -0,0 +1,110 @@ + + + + + + Counter | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Counter

We’re going build the classic frontend starter app, the counter, using ReasonReact. If you’ve already installed the starter project, you can run the project now:

  1. Go to the root directory of your melange-for-react-devs-template project
  2. Run make watch to start the Melange compiler in watch mode.
  3. In another terminal window, start the webpack dev server by running make serve. As a side effect, it will open a browser tab pointed to http://localhost:8080/.

Open Index.re and you’ll see this:

re
module App = {
+  [@react.component]
+  let make = () => <div> {React.string("welcome to my app")} </div>;
+};
module App = {
+  [@react.component]
+  let make = () => <div> {React.string("welcome to my app")} </div>;
+};

This is just about the simplest component you can make, but through it, we can start to see some of the key differences of developing with ReasonReact:

  • All components must be inside a module
  • The make function renders the component and returns React.element
  • We must decorate the make function with [@react.component]
  • In JSX, we must wrap strings with calls to React.string

Let’s go over these differences in more detail.

Components are modules

In the example above, a new module named App is defined. OCaml’s modules are somewhat like JavaScript modules, with one notable difference being that there can be multiples modules inside a single file. For now, you just need to know that all components in ReasonReact are modules, and the name of the component comes from the name of the module.

The make function

The make function has the type unit => React.element, meaning it takes () as the only argument and returns an object of type React.element. You’ll need to decorate make with the attribute@react.component. We’ll go into the details later, but for now let’s just say that @react.component is there to reduce boilerplate and make our code more readable and easier to maintain.

Wrap strings with React.string

Unlike in normal React, we must wrap strings inside function calls to convert them to the React.element type. This is exactly what the React.string function does—if you hover over it, you’ll see that it displays the type string => React.element.

Using the App component

A little bit further down, we make use of the App component:

re
let node = ReactDOM.querySelector("#root");
+switch (node) {
+| Some(root) => ReactDOM.render(<App />, root)
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+};
let node = ReactDOM.querySelector("#root");
+switch (node) {
+| Some(root) => ReactDOM.render(<App />, root)
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+};

React.querySelector("#root") returns an option(Dom.element), meaning that if it doesn’t find the element, it returns None, and if it does find the element, it returns Some(Dom.element), i.e. the element wrapped in the Some constructor. The switch expression[1] allows you to succinctly express:

  • If node is Some(Dom.element), render the App component to the DOM
  • Otherwise if node is None, log an error message

We’ll talk more about option in the Celsius converter chapter.

The Counter component

Let’s create a counter component by creating a new file Counter.re with the following contents:

re
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0);
+
+  <div>
+    <button onClick={_evt => setCounter(v => v - 1)}>
+      {React.string("-")}
+    </button>
+    {React.string(Int.to_string(counter))}
+    <button onClick={_evt => setCounter(v => v + 1)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0);
+
+  <div>
+    <button onClick={_evt => setCounter(v => v - 1)}>
+      {React.string("-")}
+    </button>
+    {React.string(Int.to_string(counter))}
+    <button onClick={_evt => setCounter(v => v + 1)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};

This is a component with a single useState hook. It should look fairly familiar if you know about hooks in React. Note that we didn’t need to manually define a module for Counter, because all source files in OCaml are automatically modules, with the name of the module being the same as the name of the file.

Now let’s modify App so that it uses our new Counter component:

re
module App = {
+  [@react.component]
+  let make = () => <Counter />;
+};
module App = {
+  [@react.component]
+  let make = () => <Counter />;
+};

The pipe last operator

To display the number of the counter, we wrote {React.string(Int.to_string(counter))}, which converts an integer to a string, and then converts that string to React.element. In OCaml, there’s a way to apply a sequence of operations over some data so that it can be read from left to right:

reason
{counter |> Int.to_string |> React.string}
{counter |> Int.to_string |> React.string}

This uses the pipe last operator, which is useful for chaining function calls.

Basic styling

Let’s add a bit of styling to the root element of Counter:

re
<div
+  style={ReactDOMStyle.make(
+    ~padding="1em",
+    ~display="flex",
+    ~gridGap="1em",
+    (),
+  )}>
+  <button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span> {counter |> Int.to_string |> React.string} </span>
+  <button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;
<div
+  style={ReactDOMStyle.make(
+    ~padding="1em",
+    ~display="flex",
+    ~gridGap="1em",
+    (),
+  )}>
+  <button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span> {counter |> Int.to_string |> React.string} </span>
+  <button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;

Unlike in React, the style prop in ReasonReact doesn’t take a generic object, instead it takes an object of type ReactDOMStyle.t that is created by calling ReactDOMStyle.make. This isn’t a sustainable way to style our app—in the orders chapter, we’ll see how to style using CSS classes.

Congratulations! You’ve created your first ReasonReact app and component. In future chapters we’ll create more complex and interesting components.

Exercises

1. There aren’t any runtime errors in our app right now. But what happens if you try to remove the | None branch of the switch (node) expression?

2. What happens if you rename the _evt variable inside the button callback to evt?

3. Comment out the [@react.component] attribute in Counter.re. What happens?

Overview

What we covered in this section:

  • How to create and run a basic ReasonReact app
  • ReasonReact components are also modules
  • OCaml has an option type whose value can be either None or Some(_)
  • The pipe last operator is an alternate way to invoke functions that enables easy chaining of function calls
  • The style prop doesn’t take generic objects

Solutions

1. Removing the | None branch will result in a compilation error:

Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None
Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+None

Basically, the compiler is telling you to handle the None case if you want to ship your app. This is part of what makes OCaml such a type-safe language.

2. Renaming _evt to evt results in a compilation error:

Error (warning 27 [unused-var-strict]): unused variable evt.
Error (warning 27 [unused-var-strict]): unused variable evt.

OCaml wants you to use all the variables you declare, unless they begin with _ (underscore).

3. Commenting out [@react.component] in Counter.re will trigger a compilation error in Index.re, at the place where Counter component is used:

File "Index.re", line 3, characters 19-27:
+3 |   let make = () => <Counter />;
+                       ^^^^^^^^^^^
+Error: Unbound value Counter.makeProps
File "Index.re", line 3, characters 19-27:
+3 |   let make = () => <Counter />;
+                       ^^^^^^^^^^^
+Error: Unbound value Counter.makeProps

For now, don’t worry about what Counter.makeProps is or where it came from—just remember that you need to put the [@react.component] attribute above your make function if you want your component to be usable in JSX. This is a very common newbie mistake. See the PPX chapter for more details.


Source code for this chapter can be found in the Melange for React Developers repo.


  1. Despite the name, don’t confuse OCaml’s switch expressions with JavaScript’s switch statements. ↩︎

+ + + + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 00000000..22516994 --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"installation_index.md":"a1fbd0b6","todo.md":"6e486e47","readme.md":"3ce0111a","celsius-converter-option_index.md":"df50f66c","counter_index.md":"6e6af5ae","intro_index.md":"987c5fae","celsius-converter-exception_index.md":"ba9a3483","index.md":"a20614f4","intro-to-dune_index.md":"a5b8b6ca","numeric-types_index.md":"6aeeacfe","order-confirmation_index.md":"c17c7e32"} diff --git a/index.html b/index.html new file mode 100644 index 00000000..c53cc5a4 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + + + + + Melange for React Devs | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Melange for React Devs

A project-based, guided introduction to Melange, for React developers

+ + + + \ No newline at end of file diff --git a/installation/index.html b/installation/index.html new file mode 100644 index 00000000..d82d7830 --- /dev/null +++ b/installation/index.html @@ -0,0 +1,42 @@ + + + + + + Installation | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Installation

Prerequisites

Opam

We need opam, the OCaml Package Manager. There are many ways to install it depending on your platform, but let’s go with the simplest method:

bash
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
+opam init
+eval $(opam env)
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
+opam init
+eval $(opam env)

While opam init is running, it will prompt you with something like

Do you want opam to modify ~/.profile?
Do you want opam to modify ~/.profile?

Type y to agree.

After the installation completes, run

opam --version
opam --version

to verify that it succeeded.

Download and run the starter project

Let’s make sure that everything works by downloading and running our project template melange-for-react-devs-template.

bash
git clone https://github.com/melange-re/melange-for-react-devs-template
+cd melange-for-react-devs-template
+make init
+make build
+make serve
git clone https://github.com/melange-re/melange-for-react-devs-template
+cd melange-for-react-devs-template
+make init
+make build
+make serve

While make init is running, consider grabbing some coffee or other beverage, as it might take a while to fetch all the dependencies and build them. The last command, make serve, should open a tab in your default browser which points to http://localhost:8080/ and shows you a typical “Hello World” page. If you see this page, then the project was successfully installed!

Visual Studio Code Extension

  1. Open the Extensions tab in Visual Studio Code and search for “ocaml”.
  2. Install the OCaml Platform extension from OCaml Labs.
  3. To verify that the extension worked, open the melange-for-react-devs project in Visual Studio Code. OCaml code should be syntax highlighted, and you should see type annotations when you hover over variables.
  4. To enable auto-formatting, open your User Settings JSON file and add this snippet:
json
"[reason]": {
+  "editor.formatOnSave": true,
+  "editor.defaultFormatter": "ocamllabs.ocaml-platform"
+}
"[reason]": {
+  "editor.formatOnSave": true,
+  "editor.defaultFormatter": "ocamllabs.ocaml-platform"
+}
+ + + + \ No newline at end of file diff --git a/intro-to-dune/index.html b/intro-to-dune/index.html new file mode 100644 index 00000000..87f0a862 --- /dev/null +++ b/intro-to-dune/index.html @@ -0,0 +1,176 @@ + + + + + + Introduction to Dune | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Introduction to Dune

Depending on how you’ve been following along, you may have several components in your project. Since these components don’t have much in common with each other, it makes sense to put them in separate, independent apps. To do that, we’ll have to spend a little time with Dune. Dune is a build system designed for OCaml projects, and it has many useful features. For our purposes, the feature of primary interest is its built-in support for Melange.

dune-project file

The dune-project file specifies metadata for a project, and should appear in the root directory of your project. If you’ve been using the starter project, then you’ve been using Dune this whole time and therefore already have a dune-project file:

clj
(lang dune 3.8)
+
+; Use version 0.1 of the melange plugin for dune
+
+(using melange 0.1)
+
+; Set the name which is used by error messages
+
+(name melange-for-react-devs)
(lang dune 3.8)
+
+; Use version 0.1 of the melange plugin for dune
+
+(using melange 0.1)
+
+; Set the name which is used by error messages
+
+(name melange-for-react-devs)

The line

clj
(using melange 0.1)
(using melange 0.1)

is necessary because we have to manually enable the Melange extension for Dune in order to use it. Note that the version of the Melange Dune extension is independent of the version of Melange we’re using.

Technically, dune-project accepts many more metadata fields, but it’s best to keep it minimal. Other than name, it makes more sense to put the rest of your project’s metadata fields in your .opam file, which we’ll cover later.

dune-project files use S-expressions, which might make you think of the Lisp programming language. However, S-expressions are just a convenient syntax for encoding structured data, and Dune doesn’t have the power of a full scripting language.

Each S-expression at the top level is a known as a stanza. All the possible stanzas you can use in dune-project can be found in Dune’s Stanza Reference.

dune files

Besides dune-project, Dune also looks at the dune files in our project. Basically, dune files tell Dune about directories, executables, libraries, tests, and anything else of interest. For example, here’s the dune file inside the root directory of your project:

clj
; `dirs` is a stanza to tell dune which subfolders from the current folder
+; (where the `dune` file is) it should process. Here it is saying to include
+; all directories that don't start with . or _, but exclude node_modules.
+
+(dirs :standard \ node_modules)
+
+; `melange.emit` is a Dune stanza that will produce build rules to generate
+; JavaScript files from sources using the Melange compiler
+; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
+
+(melange.emit
+ ; The `target` field is used by Dune to put all JavaScript artifacts in a
+ ; specific folder inside `_build/default`
+ (target output)
+ ; Here's the list of dependencies of the stanza. In this case (being
+ ; `melange.emit`), Dune will look into those dependencies and generate rules
+ ; with JavaScript targets for the modules in those libraries as well.
+ ; Caveat: the libraries need to be specified with `(modes melange)`.
+ (libraries reason-react)
+ ; The `preprocess` field lists preprocessors which transform code before it is
+ ; compiled. melange.ppx allows to use Melange attributes [@mel. ...]
+ ; (https://melange.re/v2.0.0/communicate-with-javascript/#attributes)
+ ; reason-react-ppx allows to use JSX for ReasonReact components by using the
+ ; [@JSX] attributes from Reason: https://reasonml.github.io/docs/en/jsx
+ (preprocess
+  (pps melange.ppx reason-react-ppx))
+ ; module_systems lets you specify commonjs (the default) or es6
+ (module_systems es6))
; `dirs` is a stanza to tell dune which subfolders from the current folder
+; (where the `dune` file is) it should process. Here it is saying to include
+; all directories that don't start with . or _, but exclude node_modules.
+
+(dirs :standard \ node_modules)
+
+; `melange.emit` is a Dune stanza that will produce build rules to generate
+; JavaScript files from sources using the Melange compiler
+; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
+
+(melange.emit
+ ; The `target` field is used by Dune to put all JavaScript artifacts in a
+ ; specific folder inside `_build/default`
+ (target output)
+ ; Here's the list of dependencies of the stanza. In this case (being
+ ; `melange.emit`), Dune will look into those dependencies and generate rules
+ ; with JavaScript targets for the modules in those libraries as well.
+ ; Caveat: the libraries need to be specified with `(modes melange)`.
+ (libraries reason-react)
+ ; The `preprocess` field lists preprocessors which transform code before it is
+ ; compiled. melange.ppx allows to use Melange attributes [@mel. ...]
+ ; (https://melange.re/v2.0.0/communicate-with-javascript/#attributes)
+ ; reason-react-ppx allows to use JSX for ReasonReact components by using the
+ ; [@JSX] attributes from Reason: https://reasonml.github.io/docs/en/jsx
+ (preprocess
+  (pps melange.ppx reason-react-ppx))
+ ; module_systems lets you specify commonjs (the default) or es6
+ (module_systems es6))

Like dune-project, a dune file consists of one or more stanzas. The first stanza is dirs, which tells Dune which directories to include in the build. Note that the stanzas accepted in dune files are not the same as the ones accepted by dune-project. See all possible dune stanzas in Dune’s Stanza Reference.

melange.emit stanza

The main stanza of interest for us is melange.emit, which tells Dune to turn our OCaml files into JavaScript files. The fields we give to melange.emit here are target, libraries, preprocess, and module_systems, which are ones that we need to use for pretty much every Melange project.

A note about the target field: It is referenced in the serve npm script, whose command is

bash
webpack serve --open --mode development --entry ./_build/default/output/Index.js
webpack serve --open --mode development --entry ./_build/default/output/Index.js

If you change the value of target to, say, stuff, the value of the --entry option must be changed to

./_build/default/stuff/Index.js
./_build/default/stuff/Index.js

For more details about where JavaScript output files end up in the build directory, see JavaScript artifacts layout.

INFO

In this dune file, we’re only concerned with building JavaScript to run in the browser, but if we also wanted to build JavaScript to run on Node, we’d include another melange.emit stanza specifically for that. See melange-opam-template for an example of building for Node.

Counter app directory

Create a new directory src/counter, which will contain a new app that only renders the Counter component. Then make sure this new directory contains:

  • Counter.re (move from root directory to src/counter)

  • dune file that just has a melange.emit stanza

    clj
    ; `melange.emit` is a Dune stanza that will produce build rules to generate
    +; JavaScript files from sources using the Melange compiler
    +; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
    +
    +(melange.emit
    + ; The `target` field is used by Dune to put all JavaScript artifacts in a
    + ; specific folder inside `_build/default`
    + (target output)
    + ; Here's the list of dependencies of the stanza. In this case (being
    + ; `melange.emit`), Dune will look into those dependencies and generate rules
    + ; with JavaScript targets for the modules in those libraries as well.
    + ; Caveat: the libraries need to be specified with `(modes melange)`.
    + (libraries reason-react)
    + ; The `preprocess` field lists preprocessors which transform code before it is
    + ; compiled. These enable, for example, the use of JSX in .re files.
    + (preprocess
    +  (pps melange.ppx reason-react-ppx))
    + ; module_systems lets you specify commonjs (the default) or es6
    + (module_systems es6))
    ; `melange.emit` is a Dune stanza that will produce build rules to generate
    +; JavaScript files from sources using the Melange compiler
    +; https://dune.readthedocs.io/en/stable/melange.html#melange-emit
    +
    +(melange.emit
    + ; The `target` field is used by Dune to put all JavaScript artifacts in a
    + ; specific folder inside `_build/default`
    + (target output)
    + ; Here's the list of dependencies of the stanza. In this case (being
    + ; `melange.emit`), Dune will look into those dependencies and generate rules
    + ; with JavaScript targets for the modules in those libraries as well.
    + ; Caveat: the libraries need to be specified with `(modes melange)`.
    + (libraries reason-react)
    + ; The `preprocess` field lists preprocessors which transform code before it is
    + ; compiled. These enable, for example, the use of JSX in .re files.
    + (preprocess
    +  (pps melange.ppx reason-react-ppx))
    + ; module_systems lets you specify commonjs (the default) or es6
    + (module_systems es6))
  • Index.re to render the app to the DOM

    re
    module App = {
    +  [@react.component]
    +  let make = () => <Counter />;
    +};
    +
    +let node = ReactDOM.querySelector("#root");
    +switch (node) {
    +| None =>
    +  Js.Console.error("Failed to start React: couldn't find the #root element")
    +| Some(root) => ReactDOM.render(<App />, root)
    +};
    module App = {
    +  [@react.component]
    +  let make = () => <Counter />;
    +};
    +
    +let node = ReactDOM.querySelector("#root");
    +switch (node) {
    +| None =>
    +  Js.Console.error("Failed to start React: couldn't find the #root element")
    +| Some(root) => ReactDOM.render(<App />, root)
    +};
  • Makefile to serve the app using webpack dev server

    make
    .PHONY: serve
    +serve:
    +	app=counter make -C ../.. serve
    .PHONY: serve
    +serve:
    +	app=counter make -C ../.. serve

After you’ve added those files, your src/counter directory should look like this:

src/counter
+├─ Counter.re
+├─ dune
+├─ Index.re
+└─ Makefile
src/counter
+├─ Counter.re
+├─ dune
+├─ Index.re
+└─ Makefile

Why Makefile

You might be wondering why we’re using a Makefile instead of adding another npm script. In OCaml projects, usage of the Make build automation tool is common, and this includes Melange-related projects. So let’s take a short detour to explain the Makefile we just added.

Anatomy of Makefile

In case you’re not familiar with Make, here’s a breakdown of src/counter/Makefile:

make
.PHONY: serve
+serve:
+	app=counter make -C ../.. serve
.PHONY: serve
+serve:
+	app=counter make -C ../.. serve
  • There’s only a single rule here, and its target is serve.
  • .PHONY: serve is used to indicate that serve is a phony target, meaning serve is not a file we want to generate but just a label for an action. In a simple Makefile like this one, declaring phony targets isn’t strictly necessary.
  • The line under serve: is the recipe, basically the command that will be executed when we run make serve at the command line.
    • app=counter sets the app environment variable to counter, which is the name of the directory this Makefile lives in
    • The -C option tells Make to change the directory before reading the Makefile. In effect, it means we’re running the serve rule in the root directory’s Makefile.

Root directory Makefile

Currently, the serve rule in root directory’s Makefile can only run the app in the root directory. We want it to be able to run the app in src/counter, so we need to change it:

make
.PHONY: serve
+serve: ## Serve the application with a local HTTP server
+	npx webpack serve --open --mode development --entry ./_build/default/src/$(app)/output/src/$(app)/Index.js
.PHONY: serve
+serve: ## Serve the application with a local HTTP server
+	npx webpack serve --open --mode development --entry ./_build/default/src/$(app)/output/src/$(app)/Index.js

We basically copied the serve npm command from package.json to create the recipe for this rule, but instead of a fixed value for the --entry option, we use

./_build/default/src/$(app)/output/src/$(app)/Index.js
./_build/default/src/$(app)/output/src/$(app)/Index.js

This means that the entry script served by webpack dev server depends on the app environment variable, which is provided by src/counter/Makefile.

You’re now ready to run the new Counter app you created! Go into the src/counter directory and run

make serve
make serve

It should open a new tab in your default browser to http://localhost:8080/ and display your Counter component.

Cleanup

Feel to delete the Index.re file in the root directory. You won’t need it anymore for this or later chapters. You can also delete:

  • The scripts section of yourpackage.json file
  • The melange.emit stanza from the dune file in the root directory

Rationale for monorepo structure

Going forward, we’re going to use a monorepo where projects are separate apps that are developed in their own directory. Each project directory will have its own dune file with its own melange.emit stanza. We want to use a monorepo because most projects will have very similar dependencies, so it seems overkill to create new dune-project, .opam, and package.json files[1] for every single project.

INFO

Melange documentation’s guidelines for melange.emit recommends you put the melange.emit stanza in the dune file in the project’s root directory. We are no longer doing that going forward, but this is still great advice if your repo only contains a single app!

Huzzah! You created a new dune file to build an app and a Makefile to serve that app locally. In future chapters, we assume that you will use the same directory structure for each new app you build.

Exercises

1. Repeat the steps we did for Counter and create a separate app for Celsius Converter.

2. Delete reason-react-ppx from src/counter/dune’s melange.emit stanza. What compiler errors do you get?

3. You might have noticed that every recipe in the Makefile is prefixed by a tab. What happens if you replace the tab in front of the serve rule’s recipe with four spaces?

Overview

  • Dune is the build system we use to build Melange projects
  • The dune-project file describes the metadata for your project, primarily:
    • The version of Dune you’re using
    • The version of the Melange plugin for Dune you’re using
    • The name of your project
  • dune files describe things of interest to Dune, for example:
    • Which directories to include and which to exclude
    • Which directories contain code that should be transpiled to JavaScript, using the melange.emit stanza
  • Make is a build automation tool commonly used in the OCaml world
    • Makefiles contain rules which can run commands based on the target you pass to the make command

Solutions

1. Creating a separate app for Celsius Converter, with its own dune, Makefile, and Index.re files, should look something like this.

2. Deleting reason-react-ppx from src/counter/dune will result in a compilation error:

File "src/counter/Counter.re", line 5, characters 2-6:
+5 |   <div
+      ^^^^
+Error: Unbound value div
File "src/counter/Counter.re", line 5, characters 2-6:
+5 |   <div
+      ^^^^
+Error: Unbound value div

That’s because putting reason-react-ppx in the preprocess/pps field will transform function calls to div (which isn’t defined anywhere) into calls to React.createElement("div", ...)[2].

3. Replacing the tab in front of the serve rule’s recipe with four spaces will result in a Makefile error:

Makefile:42: *** missing separator.  Stop.
Makefile:42: *** missing separator.  Stop.

The line number where it expects the tab is 42. It is a very common mistake to write spaces instead of tabs in a Makefile. Fortunately, most code editors know that when you press the Tab key inside a Makefile, you mean to add a tab character instead of space characters.


Source code for this chapter can be found in the Melange for React Developers repo:


  1. The full list of files we’d need to create for every project would actually be dune-project, .opam, package.json, public/index.html, and webpack.config.js. ↩︎

  2. More details about how JSX gets translated can be found here and here. ↩︎

+ + + + \ No newline at end of file diff --git a/intro/index.html b/intro/index.html new file mode 100644 index 00000000..c7e127f3 --- /dev/null +++ b/intro/index.html @@ -0,0 +1,23 @@ + + + + + + Melange for React Developers | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Melange for React Developers

WARNING

This is a work in progress.

Motivation

This is a project-based, guided introduction to Melange and its ecosystem. Because Melange uses both OCaml and JavaScript ecosystems, there are quite a few tools and concepts to learn. Therefore we try to make each chapter small and digestible, not introducing too many things at once.

Audience

You should already know how to make frontend applications in JavaScript, in particular with React. You should be interested in learning how to leverage your existing knowledge to build apps using ReasonReact. You do not need to know OCaml[1]—we’ll slowly introduce the basics of the language throughout the tutorial. That said, a good complement to this guide is OCaml Programming: Correct + Efficient + Beautiful, which teaches the language from the ground up and goes much deeper into its features.

Chapters and topics

TitleSummaryTopics covered
CounterNumber that can be incremented or decrementedmodule, Option, pipe last operator, function chaining, switch
Melange PlaygroundUse Melange Playground to explore OCaml’s numeric typesPlayground, Int, Float
Celsius ConverterSingle input that converts from Celsius to Fahrenheitpolymorphic object, exception handling, ternary expression, if-else expression, labeled argument, partial application
Celsius Converter using OptionThe same component from the last chapter but replacing exception handling with OptionOption, Option.map, when guard

…and much more to come!


  1. Because of the focus on ReasonReact, we won’t cover traditional OCaml syntax in this guide. Instead, we’ll cover the Reason syntax which works great with ReasonReact because of its first-class support for JSX. ↩︎

+ + + + \ No newline at end of file diff --git a/numeric-types/index.html b/numeric-types/index.html new file mode 100644 index 00000000..69b0a561 --- /dev/null +++ b/numeric-types/index.html @@ -0,0 +1,264 @@ + + + + + + Numeric Types | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Numeric Types

OCaml’s numeric types work differently than in JavaScript. The first thing you might notice is that OCaml makes a clear and hard distinction between integer and float types. For example:

reason
let foo = 42;   // int
+let bar = 42.1; // float
+Js.log(foo);
+Js.log(bar);
let foo = 42;   // int
+let bar = 42.1; // float
+Js.log(foo);
+Js.log(bar);

Note that you didn’t have to write the types yourself, OCaml is able to infer the types from the literals. This would also work:

reason
let foo: int = 42;
+let bar: float = 42.1;
+Js.log(foo);
+Js.log(bar);
let foo: int = 42;
+let bar: float = 42.1;
+Js.log(foo);
+Js.log(bar);

Melange Playground

Melange Playground is an interactive environment for running OCaml code and seeing its output. Paste this into the source code editor on the left side:

reason
let foo = 42;
+let bar = 42.1;
+Js.log(foo);
+Js.log(bar);
let foo = 42;
+let bar = 42.1;
+Js.log(foo);
+Js.log(bar);

In the bottom right panel, you can see the console output, which should be:

42
+42.1
42
+42.1

In the top right panel, you can see the JavaScript generated by the Melange compiler:

// Generated by Melange
+
+
+console.log(42);
+
+console.log(42.1);
+
+var foo = 42;
+
+var bar = 42.1;
+
+export {
+  foo ,
+  bar ,
+}
+/*  Not a pure module */
// Generated by Melange
+
+
+console.log(42);
+
+console.log(42.1);
+
+var foo = 42;
+
+var bar = 42.1;
+
+export {
+  foo ,
+  bar ,
+}
+/*  Not a pure module */

Note that the console.log invocations are given constants instead of the variables. That’s a nifty optimization done by Melange.

Another sweet feature is that you can hover over the variables and see their types. Try it out, and you’ll see that foo has type int while bar has type float.

The Problems pane in the bottom left corner shows error mesages when appropriate. At the moment, it shows No problems. Try type-annotating bar with int and see what happens:

reason
let foo = 42; // int
+let bar: int = 42.1; // float
+Js.log(foo);
+Js.log(bar);
let foo = 42; // int
+let bar: int = 42.1; // float
+Js.log(foo);
+Js.log(bar);

The Problems pane should now show something like this:

Line 2, 15:
+  Error This expression has type float but an expression was expected of type int
Line 2, 15:
+  Error This expression has type float but an expression was expected of type int

Sharing code snippets

Melange Playground is also an excellent way to share OCaml code snippets with your friends! As you type in the source editor, it will store your code in the code query string parameter of the URL. For example, here’s a link to the snippet we started with:

https://melange.re/v2.1.0/playground/?language=Reason&code=bGV0IGZvbyA9IDQyOwpsZXQgYmFyID0gNDIuMTsKSnMubG9nKGZvbyk7CkpzLmxvZyhiYXIpOw%3D%3D&live=off

Comparison operators

In Melange Playground, change your program to this:

reason
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(foo == bar);
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(foo == bar);

You’ll get a compiler error for the last line that says

This expression has type float but an expression was expected of type int
This expression has type float but an expression was expected of type int

Unlike JavaScript, there are no implicit conversions in OCaml. Therefore you cannot expect to compare an integer and a float together, unless you convert one of the values so that both values have the same type. To make the last line compile, you can change it to:

reason
Js.log(foo == Int.of_float(bar));
Js.log(foo == Int.of_float(bar));

Another way to fix the last line is to convert foo from an int to a float:

reason
Js.log(Float.of_int(foo) == bar);
Js.log(Float.of_int(foo) == bar);

The same-type restriction applies to all the comparison operators:

reason
Js.log(3 < 33);
+Js.log(44. > 4.);
+Js.log(5 <= 55);
+Js.log(66. >= 6.);
Js.log(3 < 33);
+Js.log(44. > 4.);
+Js.log(5 <= 55);
+Js.log(66. >= 6.);

Arithmetic operators

What about addition? From what you’ve already seen, you can probably guess that Js.log(42 + 16.0) won’t compile. However, you may be surprised to discover that Js.log(42.0 + 16.0) also won’t compile! That’s because OCaml uses separate arithmetic operators for floats. What will compile is this:

reason
Js.log(42.0 +. 16.0); // prints 58
Js.log(42.0 +. 16.0); // prints 58

Here are examples of the other arithmetic operators, try them out in the playground:

reason
Js.log(66.0 -. 6.0);
+Js.log(66.0 *. 6.0);
+Js.log(66.0 /. 6.0);
Js.log(66.0 -. 6.0);
+Js.log(66.0 *. 6.0);
+Js.log(66.0 /. 6.0);

Notice that all float arithmetic operators end with . (period), just like float literals.

They’re just Number

Underneath the covers, foo and bar are both instances of JavaScript’s Number type:

reason
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(Js.typeof(foo)); // prints "number"
+Js.log(Js.typeof(bar)); // prints "number"
let foo = 42;   // int
+let bar = 42.0; // float
+Js.log(Js.typeof(foo)); // prints "number"
+Js.log(Js.typeof(bar)); // prints "number"

Refer to the Melange docs for a complete rundown of how OCaml types get translated to JavaScript types.

Widgets in the playground

Melange Playground can also render ReasonReact components! Click the Live button next to the JavaScript output button. Now paste in the code to render the Counter component from the previous chapter:

re
module Counter = {
+  [@react.component]
+  let make = () => {
+    let (counter, setCounter) = React.useState(() => 0);
+
+    <div
+      style={ReactDOMStyle.make(
+        ~padding="1em",
+        ~display="flex",
+        ~gridGap="1em",
+        (),
+      )}>
+      <button onClick={_evt => setCounter(v => v - 1)}>
+        {React.string("-")}
+      </button>
+      <span> {counter |> Int.to_string |> React.string} </span>
+      <button onClick={_evt => setCounter(v => v + 1)}>
+        {React.string("+")}
+      </button>
+    </div>;
+  };
+};
+
+switch (ReactDOM.querySelector("#preview")) {
+| None => Js.log("Failed to start React: couldn't find the #preview element")
+| Some(root) => ReactDOM.render(<Counter />, root)
+};
module Counter = {
+  [@react.component]
+  let make = () => {
+    let (counter, setCounter) = React.useState(() => 0);
+
+    <div
+      style={ReactDOMStyle.make(
+        ~padding="1em",
+        ~display="flex",
+        ~gridGap="1em",
+        (),
+      )}>
+      <button onClick={_evt => setCounter(v => v - 1)}>
+        {React.string("-")}
+      </button>
+      <span> {counter |> Int.to_string |> React.string} </span>
+      <button onClick={_evt => setCounter(v => v + 1)}>
+        {React.string("+")}
+      </button>
+    </div>;
+  };
+};
+
+switch (ReactDOM.querySelector("#preview")) {
+| None => Js.log("Failed to start React: couldn't find the #preview element")
+| Some(root) => ReactDOM.render(<Counter />, root)
+};

Note that we explicitly defined a module for the Counter component this time because we can’t use multiple files in Melange Playground.

Let’s make the counter look a little more impressive. Add a new module called Styles which contains all the styles we want to use:

re
module Styles = {
+  // Alias the function to save on keystrokes
+  let make = ReactDOMStyle.make;
+
+  let root =
+    make(
+      ~fontSize="2em",
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      ~alignItems="center",
+      (),
+    );
+
+  let button =
+    make(
+      ~fontSize="1em",
+      ~border="1px solid white",
+      ~borderRadius="0.5em",
+      ~padding="0.5em",
+      (),
+    );
+
+  let number = make(~minWidth="2em", ~textAlign="center", ());
+};
module Styles = {
+  // Alias the function to save on keystrokes
+  let make = ReactDOMStyle.make;
+
+  let root =
+    make(
+      ~fontSize="2em",
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      ~alignItems="center",
+      (),
+    );
+
+  let button =
+    make(
+      ~fontSize="1em",
+      ~border="1px solid white",
+      ~borderRadius="0.5em",
+      ~padding="0.5em",
+      (),
+    );
+
+  let number = make(~minWidth="2em", ~textAlign="center", ());
+};

And then update the JSX in our make function to use the style objects in Styles:

re
<div style=Styles.root>
+  <button style=Styles.button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span style=Styles.number>
+    {counter |> Int.to_string |> React.string}
+  </span>
+  <button style=Styles.button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;
<div style=Styles.root>
+  <button style=Styles.button onClick={_evt => setCounter(v => v - 1)}>
+    {React.string("-")}
+  </button>
+  <span style=Styles.number>
+    {counter |> Int.to_string |> React.string}
+  </span>
+  <button style=Styles.button onClick={_evt => setCounter(v => v + 1)}>
+    {React.string("+")}
+  </button>
+</div>;

Here’s the playground link for the fully-styled Counter component.

W00t! You are now empowered to use numbers in your OCaml programs.

Exercises

1. Convert the Counter component we created in the previous chapter to use float instead of integer. Make the - button decrement by 0.5 and the + button increment by 1.5.

2. Add an int64 value to your program in Melange Playground:

reason
let baz = 42_000_000_000L; // int64
+Js.log(baz);
let baz = 42_000_000_000L; // int64
+Js.log(baz);

Note the use of underscores to make the large number more readable. What is the JavaScript representation of int64?

3. How do you add two int64 values? Hint: Take a look at the standard library’s Int64 module.

Overview

  • Integer and float are separate types in OCaml, but both translate to JavaScript’s Number type once your program is compiled
  • Comparison operators expect the values on both sides to be the same type
  • Integer arithmetic operators are the same as in JavaScript, but float arithmetic operators are different (they end with .) and only accept floats as inputs
  • Melange Playground is a great way to play around with short OCaml programs and has many helpful features:
    • Display console output
    • Display compiled JavaScript output
    • Display error messages when your code isn’t compiling
    • Show type hints on hover
    • Share code snippets via URL
    • Render ReasonReact components

Solutions

1. A Counter component that uses float instead of integer would look something like this:

re
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0.0);
+
+  <div
+    style={ReactDOMStyle.make(
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      (),
+    )}>
+    <button onClick={_evt => setCounter(v => v -. 0.5)}>
+      {React.string("-")}
+    </button>
+    <span> {counter |> Float.to_string |> React.string} </span>
+    <button onClick={_evt => setCounter(v => v +. 1.5)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};
[@react.component]
+let make = () => {
+  let (counter, setCounter) = React.useState(() => 0.0);
+
+  <div
+    style={ReactDOMStyle.make(
+      ~padding="1em",
+      ~display="flex",
+      ~gridGap="1em",
+      (),
+    )}>
+    <button onClick={_evt => setCounter(v => v -. 0.5)}>
+      {React.string("-")}
+    </button>
+    <span> {counter |> Float.to_string |> React.string} </span>
+    <button onClick={_evt => setCounter(v => v +. 1.5)}>
+      {React.string("+")}
+    </button>
+  </div>;
+};

2. JavaScript’s Number type doesn’t have enough precision to represent in64 values. They’re instead represented by an array of two numbers [high, low], where high is signed, low is unsigned.

3. You can add two int64 values using Int64.add, e.g.

reason
let result = Int64.add(42L, 16L);
+Js.log(result); // prints [0,58]
let result = Int64.add(42L, 16L);
+Js.log(result); // prints [0,58]

Source code for this chapter can be found in the Melange for React Developers repo.

+ + + + \ No newline at end of file diff --git a/order-confirmation/index.html b/order-confirmation/index.html new file mode 100644 index 00000000..6134d301 --- /dev/null +++ b/order-confirmation/index.html @@ -0,0 +1,317 @@ + + + + + + Order Confirmation | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Order Confirmation

The famed restauranteur Madame Jellobutter has opened a hot new pop-up restaurant called Emoji Cafe, and you’ve been commissioned to build the order confirmation widget on its website. Feeling adventurous, you decide to build it using Melange.

Start by creating a new directory src/order-confirmation and give it the same directory structure as we showed you in the previous chapter:

src/order-confirmation
+├─ dune
+├─ Index.re
+├─ Makefile
+└─ Item.re
src/order-confirmation
+├─ dune
+├─ Index.re
+├─ Makefile
+└─ Item.re

The dune file can be copied from any of the existing projects. The Makefile can also be copied over, but remember to update the value of the app environment variable to order-confirmation. The .re files can be empty for now.

Variant type Item.t

For the time being, there are only two items you can order at Emoji Cafe, the sandwich or the burger. In Item.re, add a new type:

re
type t =
+  | Sandwich
+  | Burger;
type t =
+  | Sandwich
+  | Burger;

This is a variant type[1] named t with two constructors, Sandwich and Burger. In OCaml, it is customary for the primary type of a module to be called t. This convention makes sense because in other modules, this type will be referred to as Item.t.

The Item module should contain helper functions that return the price and the emoji[2] for a given item. First, add the toPrice function:

re
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 15.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 15.
+  };

If Madame Jellobutter decides to add a hotdog to the menu, you would need to:

  • Add a Hotdog constructor to Order.t
  • Add a | Hotdog branch to the switch expression of Order.toPrice

Your OCaml code would fail to compile if you added Hotdog or removed Sandwich from Item.t without also updating Item.toPrice. This is one of the great advantages of variant types: changing the constructors will force you to change the relevant parts of your code.

Wildcard in switch expressions

If Madame Jellobutter decides to do a promotion that lowers the price of burgers so that they’re the same price as sandwiches, you could rewrite Item.toPrice to:

reason
let toPrice = t =>
+  switch (t) {
+  | _ => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | _ => 10.
+  };

The underscore (_) here serves as a wildcard matching any constructor. However, this would be a very bad idea! Now changing the constructors in Item.t would not force you to change Item.toPrice accordingly. A superior version would be:

reason
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich => 10.
+  | Burger => 10.
+  };

Since OCaml’s pattern-matching syntax allows you to combine branches, you can simplify it to:

reason
let toPrice = t =>
+  switch (t) {
+  | Sandwich
+  | Burger => 10.
+  };
let toPrice = t =>
+  switch (t) {
+  | Sandwich
+  | Burger => 10.
+  };

In any case, you should strive to avoid wildcards. The OCaml Way is to explicitly match all constructors in your switch expressions.

A fun syntax for switch

There’s an alternate, shorter syntax for functions whose entire body is a switch expression. It’s called fun, and we can rewrite Item.toPrice to use it:

re
let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.;
let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.;

We can also define toEmoji using the fun syntax:

re
let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js};
let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js};

Using the fun syntax is completely equivalent to using a switch expression, so it’s up to your personal taste whether you want to use one or the other.

Item.make

Now we’re ready to define the make function which will render the Item component:

re
[@react.component]
+let make = (~item: t) =>
+  <tr>
+    <td> {item |> toEmoji |> React.string} </td>
+    <td>
+      {item
+       |> toPrice
+       |> Js.Float.toFixedWithPrecision(~digits=2)
+       |> React.string}
+    </td>
+  </tr>;
[@react.component]
+let make = (~item: t) =>
+  <tr>
+    <td> {item |> toEmoji |> React.string} </td>
+    <td>
+      {item
+       |> toPrice
+       |> Js.Float.toFixedWithPrecision(~digits=2)
+       |> React.string}
+    </td>
+  </tr>;

The make function has a single labeled argument, ~item, of type Item.t. This effectively means the Item component has a single prop named item.

Note that this renders a single row of a table. We’ll need another component to render a table containing all items in an order.

Order component

Create a new file src/order-confirmation/Order.re and add the following code:

re
type t = array(Item.t);
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items
+    |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items |> Js.Array.map(item => <Item item />) |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td>
+          {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+        </td>
+      </tr>
+    </tbody>
+  </table>;
+};
type t = array(Item.t);
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items
+    |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items |> Js.Array.map(item => <Item item />) |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td>
+          {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+        </td>
+      </tr>
+    </tbody>
+  </table>;
+};

There’s a lot going on here:

  • The primary type of Order is array(Item.t), which is an array of variants.
  • The Order.make function has a single labeled argument, ~items, of type t. This means the Order component has a single prop named items.
  • We sum up the prices of all items using Js.Array.reduce, which is the Melange binding to JavaScript’s Array.reduce method. Note that Js.Array.reduce requires the initial value to be passed in.
  • For each order, we render an Item component via Js.Array.map, which is the Melange binding to the Array.map method.

React.array

You might have noticed that we need a call to React.array after the call to Js.Array.map:

reason
{items |> Js.Array.map(item => <Item item />) |> React.array}
{items |> Js.Array.map(item => <Item item />) |> React.array}

If we leave off the call to React.array, we’d get this error:

File "src/order-confirmation/Order.re", lines 12, characters 6-12:
+12 |         {items |> Js.Array.map(item => <Item item />)}
+             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This expression has type React.element array
+       but an expression was expected of type React.element
File "src/order-confirmation/Order.re", lines 12, characters 6-12:
+12 |         {items |> Js.Array.map(item => <Item item />)}
+             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This expression has type React.element array
+       but an expression was expected of type React.element

We get this error primarily because collections in OCaml can only contain elements of the same type. The tbody element expects children of type React.element[3], but the call to Js.Array.map returns array(React.element), which creates a type mismatch. To make the actual type match the expected type, we must add a call to React.array which turns array(React.element) to React.element.

To better see what types are at play, it might make sense to refactor Order.make like so:

re
let total =
+  items
+  |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+let itemRows: array(React.element) =
+  items |> Js.Array.map(item => <Item item />);
+
+<table>
+  <tbody>
+    {itemRows |> React.array}
+    <tr>
+      <td> {React.string("Total")} </td>
+      <td>
+        {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+      </td>
+    </tr>
+  </tbody>
+</table>;
let total =
+  items
+  |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+let itemRows: array(React.element) =
+  items |> Js.Array.map(item => <Item item />);
+
+<table>
+  <tbody>
+    {itemRows |> React.array}
+    <tr>
+      <td> {React.string("Total")} </td>
+      <td>
+        {total |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string}
+      </td>
+    </tr>
+  </tbody>
+</table>;

In reality, React.array is just there to make the OCaml compiler happy—it doesn’t actually change the the underlying JavaScript object. For example, try running the following code in the playground:

re
let elemArray: array(React.element) =
+  [|"a", "b", "c"|] |> Js.Array.map(x => React.string(x));
+Js.log(elemArray);
+Js.log(React.array(elemArray));
let elemArray: array(React.element) =
+  [|"a", "b", "c"|] |> Js.Array.map(x => React.string(x));
+Js.log(elemArray);
+Js.log(React.array(elemArray));

If you look at the JavaScript output, you’ll see that the two calls to Js.log get compiled to

javascript
console.log(elemArray);
+
+console.log(elemArray);
console.log(elemArray);
+
+console.log(elemArray);

Index.re

Render the Order component inside src/order-confirmation/Index.re:

re
module App = {
+  let items: Order.t = [|Sandwich, Burger, Sandwich|];
+
+  [@react.component]
+  let make = () =>
+    <div>
+      <h1> {React.string("Order confirmation")} </h1>
+      <Order items />
+    </div>;
+};
+
+let node = ReactDOM.querySelector("#root");
+switch (node) {
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+| Some(root) => ReactDOM.render(<App />, root)
+};
module App = {
+  let items: Order.t = [|Sandwich, Burger, Sandwich|];
+
+  [@react.component]
+  let make = () =>
+    <div>
+      <h1> {React.string("Order confirmation")} </h1>
+      <Order items />
+    </div>;
+};
+
+let node = ReactDOM.querySelector("#root");
+switch (node) {
+| None =>
+  Js.Console.error("Failed to start React: couldn't find the #root element")
+| Some(root) => ReactDOM.render(<App />, root)
+};

Run make serve inside src/order-confirmation to see your new app in action.

Js.Array.mapi

Open your browser’s dev console, where you should see a warning:

Warning: Each child in a list should have a unique "key" prop.
Warning: Each child in a list should have a unique "key" prop.

Oops, we forgot the set the key props! One way to fix this is to use Js.Array.mapi instead[4] so we can set key based on the index of the element:

re
items
+|> Js.Array.mapi((item, index) =>
+     <Item key={"item-" ++ string_of_int(index)} item />
+   )
+|> React.array
items
+|> Js.Array.mapi((item, index) =>
+     <Item key={"item-" ++ string_of_int(index)} item />
+   )
+|> React.array

The Js.Array.mapi function is also a binding to the Array.map method, but unlike Js.Array.map, it passes the element and the index into the callback. If you hover over it, you’ll see that it has the type signature

(('a, int) => 'b, array('a)) => array('b)
(('a, int) => 'b, array('a)) => array('b)

When a JavaScript function has optional arguments, it’s common to create multiple OCaml functions that bind to it. We’ll discuss this in more detail later.


Wunderbar! You’ve got a basic order confirmation component, but it looks… not so great[5]. In the next chapter, we’ll see how ReasonReact components can be styled with plain old CSS.

Exercises

1. The Item component is only used inside the Order component and we don’t expect it to be used anywhere else (items rendered in a menu component would look different). Rename it to OrderItem and move it inside the Order module.

2. Add another constructor to Item.t variant type. Update the Item module’s helper functions to get your program to compile again.

3. Instead of repeatedly using value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string, add a helper function Format.currency that does the same thing.

Overview

  • By convention, the main type in a module is often named t
  • A variant is a type that has one or more constructors
    • Adding or removing constructors forces you to change the relevant parts of your code, unless you use wildcards when pattern-matching on a variant
    • Using wildcards in your switch expression makes your code less adaptable to change
  • The fun syntax helps you save a little bit of typing when you have a function whose entire body is a switch expression
  • Labeled arguments in a component’s make function are treated as props by ReasonReact.
  • The Js.Array module contains useful array functions
    • The Js.Array.reduce function is the binding to JavaScript’s Array.reduce method
    • The Js.Array.map and Js.Array.mapi functions are both bindings to JavaScript’s Array.map method
  • The React.array function is needed when you want to convert an array of React.elements to a single React.element, e.g. after a call to Js.Array.map

Solutions

1. To move the Item component from the Item module to the Order module, you’ll have to move the Item.make function to a submodule called Order.OrderItem. Then you’ll have to prefix the references to t, toPrice, and toEmoji with Item. since they’re now being referenced outside the Item module. After you’re done, src/order-confirmation/Order.re should look something like this:

re
type t = array(Item.t);
+
+module OrderItem = {
+  [@react.component]
+  let make = (~item: Item.t) =>
+    <tr>
+      <td> {item |> Item.toEmoji |> React.string} </td>
+      <td> {item |> Item.toPrice |> Format.currency} </td>
+    </tr>;
+};
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items
+       |> Js.Array.mapi((item, index) =>
+            <OrderItem key={"item-" ++ string_of_int(index)} item />
+          )
+       |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td> {total |> Format.currency} </td>
+      </tr>
+    </tbody>
+  </table>;
+};
type t = array(Item.t);
+
+module OrderItem = {
+  [@react.component]
+  let make = (~item: Item.t) =>
+    <tr>
+      <td> {item |> Item.toEmoji |> React.string} </td>
+      <td> {item |> Item.toPrice |> Format.currency} </td>
+    </tr>;
+};
+
+[@react.component]
+let make = (~items: t) => {
+  let total =
+    items |> Js.Array.reduce((acc, order) => acc +. Item.toPrice(order), 0.);
+
+  <table>
+    <tbody>
+      {items
+       |> Js.Array.mapi((item, index) =>
+            <OrderItem key={"item-" ++ string_of_int(index)} item />
+          )
+       |> React.array}
+      <tr>
+        <td> {React.string("Total")} </td>
+        <td> {total |> Format.currency} </td>
+      </tr>
+    </tbody>
+  </table>;
+};

2. After you add a HotDog constructor to Item.t, your Item module should look something like this:

re
type t =
+  | Sandwich
+  | Burger
+  | Hotdog;
+
+let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.
+  | Hotdog => 5.;
+
+let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js}
+  | Hotdog => {js|🌭|js};
type t =
+  | Sandwich
+  | Burger
+  | Hotdog;
+
+let toPrice =
+  fun
+  | Sandwich => 10.
+  | Burger => 15.
+  | Hotdog => 5.;
+
+let toEmoji =
+  fun
+  | Sandwich => {js|🥪|js}
+  | Burger => {js|🍔|js}
+  | Hotdog => {js|🌭|js};

Of course, you may have chosen a different price for the hotdog. Or maybe you didn’t add a hotdog at all, and instead added CannedFood (🥫) or PotOfFood (🍲). It’s totally up to you!

3. In order to create a helper function Format.currency, we must create a new module file called Format.re and add a currency function:

re
let currency = value =>
+  value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string;
let currency = value =>
+  value |> Js.Float.toFixedWithPrecision(~digits=2) |> React.string;

Then we can use that function like this:

reason
<td> {item |> toPrice |> Format.currency} </td>
<td> {item |> toPrice |> Format.currency} </td>

Source code for this chapter can be found in the Melange for React Developers repo.


  1. Variant types have no equivalent in JavaScript, but they are similar to TypeScript’s union enums ↩︎

  2. Recall that the name of this restaurant is Emoji Cafe, so everything from the menu to the order confirmation must use emojis. ↩︎

  3. All lowercase elements like div, span, table, etc expect their children to be of type React.element. But React components (with uppercase names) can take children of any type. ↩︎

  4. Using array indexes to set keys violates React’s rules of keys, which states that you shouldn’t generate keys while rendering. We’ll see a better way to do this later. ↩︎

  5. Madame Jellobutter was passing by and just happened to catch a glimpse of the unstyled component over your shoulder and puked in her mouth a little. ↩︎

+ + + + \ No newline at end of file diff --git a/todo.html b/todo.html new file mode 100644 index 00000000..16943d50 --- /dev/null +++ b/todo.html @@ -0,0 +1,23 @@ + + + + + + Content not yet unavailable | Melange for React Devs + + + + + + + + + + + + +
Skip to content

Content not yet unavailable

We are hard at work writing the content you requested. Please check back later.

Docendo disco, scribendo cogito

+ + + + \ No newline at end of file