diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..7207f2c --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "personal-blog-30389" + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbb58ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +firebase-debug.log* +firebase-debug.*.log* + +# Firebase cache +.firebase/ + +# Firebase config + +# Uncomment this if you'd like others to create their own Firebase project. +# For a team working on the same Firebase project(s), it is recommended to leave +# it commented so all members can deploy to the same project(s) in .firebaserc. +# .firebaserc + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..62cc780 --- /dev/null +++ b/config.toml @@ -0,0 +1,92 @@ +baseURL = "https://blog.rjbasitali.com" +languageCode = "en-us" +title = "Basit's Blog" +theme = "cactus" +copyright = "Basit Ali" # cactus will use title if copyright is not set +disqusShortname = "rjbasitali" # Used when comments is enabled. Cactus will use site title if not set +# googleAnalytics = "UA-1234-5" + + +# summaryLength = 2 + +# Main menu which appears below site header. +[[menu.main]] +name = "Home" +url = "/" +weight = 1 + +[[menu.main]] +name = "Tags" +url = "/tags" +weight = 3 + +[[menu.main]] +name = "About" +url = "/about" +weight = 4 + +[markup] + [markup.tableOfContents] + endLevel = 4 + ordered = false + startLevel = 2 + [markup.highlight] + codeFences = true + guessSyntax = false + hl_Lines = "" + lineNoStart = 1 + lineNos = true + lineNumbersInTable = false + noClasses = true + style = "dracula" + tabWidth = 4 + +[params] + + colortheme = "white" # dark, light, white, or classic + rss = true # generate rss feed. default value is false + googleAnalyticsAsync = true # use asynchronous tracking. Synchronous tracking by default + showAllPostsArchive = false # default + + # Home page settings + #description = "Hugo is a general-purpose website framework. Technically speaking, Hugo is a static site generator. Unlike systems that dynamically build a page with each visitor request, Hugo builds pages when you create or update your content. Since websites are viewed far more often than they are edited, Hugo is designed to provide an optimal viewing experience for your website’s end users and an ideal writing experience for website authors." + mainSection = "posts" # your main section + showAllPostsOnHomePage = false # default + postsOnHomePage = 5 # this option will be ignored if showAllPostsOnHomePage is set to true + tagsOverview = true # show tags overview by default. + showProjectsList = false # show projects list by default (if projects data file exists). + #projectsUrl = "https://github.com/gohugoio" # title link for projects list + + # https://gohugo.io/functions/format/#hugo-date-and-time-templating-reference + dateFormat = "2006-01-02" # default + + # Post page settings + show_updated = true # default + showReadTime = true # default + + [params.comments] + enabled = false # default + engine = "cactus_comments" # only disqus, utterances, and cactus_comments is supported + [params.comments.utterances] + repo = "/" + label = "hugo-site-name" # you can use however you want to label your name in your repo's issues + theme = "github-light" + [params.comments.cactuscomments] + siteName = "your_cactus_comments_sitename" # see https://cactus.chat/ on how to register your site name + #serverUrl = "" # Defaults to https://matrix.cactus.chat:8448 (Cactus Chat public server) + #serverName = "" # Defaults to cactus.chat + + # the value of name should be an valid font awesome icon name (brands type) + # https://fontawesome.com/icons?d=gallery&s=brands + [[params.social]] + name = "website" + link = "https://rjbasitali.com" + [[params.social]] + name = "github" + link = "https://github.com/rjbasitali" + [[params.social]] + name = "linkedin" + link = "https://www.linkedin.com/in/rjbasitali/" + [[params.social]] + name = "email" + link = "rjbasitali@gmail.com" # no need for "mailto:" in the head diff --git a/content/about.md b/content/about.md new file mode 100644 index 0000000..40b153c --- /dev/null +++ b/content/about.md @@ -0,0 +1,13 @@ +--- +title: "About" +date: 2021-07-31T22:39:25+05:00 +draft: false +--- + +**Hi, I'm Basit Ali. I'm a software developer specializing in Java, Go and Android.** + +Previously I've worked with many startups including telehealth, trivia games, logistics and more. Right now I'm working on providing video conferencing and other VoIP solutions using WebRTC, Golang and other cool technologies. + +I generally work with *Go* and *Java* for backend, *React*, *Android*, *Git*, *Postgres* and *Linux*, the technologies, especially databases can change depending on the needs of the project. + +You can contact me for any short-term consultancy projects. \ No newline at end of file diff --git a/content/contact.md b/content/contact.md new file mode 100644 index 0000000..f1e686d --- /dev/null +++ b/content/contact.md @@ -0,0 +1,9 @@ +--- +title: "Contact" +date: 2021-08-01T16:26:01+05:00 +draft: false +--- + +If you’ve got any questions, suggestions or would like to discuss a project then email me at [rjbasitali@gmail.com](mailto:rjbasitali@gmail.com). I’d be happy to hear from you. + +You can also find me on [LinkedIn](https://www.linkedin.com/in/rjbasitali/), [Github](https://github.com/rjbasitali/) and [Instagram](https://www.instagram.com/rjbasitali/). diff --git a/content/posts/writing-a-golang-middleware-for-your-http-handler.md b/content/posts/writing-a-golang-middleware-for-your-http-handler.md new file mode 100644 index 0000000..1875e55 --- /dev/null +++ b/content/posts/writing-a-golang-middleware-for-your-http-handler.md @@ -0,0 +1,160 @@ ++++ +draft = false +date = 2021-08-01T22:05:04+05:00 +title = "Writing a Middleware for your HTTP handler – Golang" +description = "" +slug = "" +authors = ["Basit Ali"] +tags = ["golang", "middleware", "http", "handler"] +categories = [] +externalLink = "" +series = [] ++++ + + +If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the `Content-Type` header only has the value `application/json` if you only support json, or maybe you want to spoof your HTTP request to change the method type from `POST`,`GET` or `PUT` to something else based on the `X-HTTP-Method-Override` header, or of course authenticate before finally passing the request to the destination HTTP handler. + + +You can achieve the following behaviour by writing a `middleware`, also known as a `filter` in some other backend frameworks. You can have as many middlewares as you want, each with a separate responsibility, and can chain them together to funnel incoming HTTP requests. + + +Writing a `middleware` in Go is pretty simple, you just need to **wrap** your `middleware` around the base HTTP handler, which so to speak is a thin **wrapper** around your HTTP handler. + + +Lets start with `http` package's `ListenAndServe` method, which listens for incoming connections and serves with the handler to handle the requests, and lets write a handler for root `"/"` path which checks for the header `Content-Type` to see if it's `application/json`, because our API only accepts JSON, and respond with following json `{"msg":"Hello world!"}` to any incoming request: + + +```go + func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", rootHandler) + http.ListenAndServe(":8080", mux) + } + + func rootHandler(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Content-Type") != "application/json" { + http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType) + return + } + w.Write([]byte(`{"msg":"Hello world!"}`)) + } +``` + + + +Of course in reality you could have a dozen of handlers each with a different endpoint, but lets keep it simple for this tutorial. + + +Now let's assume we have a dozen request handlers in our project and we want each handler to check for `Content-Type` header as we did in our `rootHandler`, we want our code to be DRY *(Don't Repeat Yourself)*. + + +Which brings us to writing a `middleware` to check the `Content-Type` header for each incoming request. Lets write a middleware and call it `wrap`: + +```go + func wrap(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // middleware logic + next.ServeHTTP(w, r) + }) + } +``` + +The `wrap` function takes in a `Handler` and returns a `Handler`, this syntax allows it to be used where we would normally use a request handler, and also allow us to chain multiple middlewares together. Now we can do something like `wrap(handler)` instead of just using `handler`, this would call our `middleware` logic before calling `next.ServeHTTP(w, r)` which can be the next middleware in the chain or a final call to our request handler. + + +In the following example, we are wrapping our `wrap` middleware around `mux` so every incoming request will pass through our middleware first: + + +```go + func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", rootHandler) + http.ListenAndServe(":8080", wrap(mux)) + } + + func rootHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"msg":"Hello world!"}`)) + } + + func wrap(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Content-Type") != "application/json" { + http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType) + return + } + next.ServeHTTP(w, r) + }) + } +``` + + +So far we've been using a single middleware, lets see multiple middlewares chained together in action. We can define multiple middlewares with the same signature as of `wrap`, replacing the comment `// middleware logic` with our code. + +>```go +> func wrap(next http.Handler) http.Handler { +> return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +> // middleware logic +> next.ServeHTTP(w, r) +> }) +> } +>``` + +Lets rename `wrap` to `enforceJSON`, and write another `middleware` which will log every incoming request's method and path, and chain them both together: + +```go + func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", rootHandler) + http.ListenAndServe(":8080", logRequest(enforceJSON(mux))) + } + + func rootHandler(w ResponseWriter, r *Request) { + w.Write([]byte(`{"msg":"Hello world!"}`)) + } + + func logRequest(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println(r.Method, r.URL.Path) // logs: GET /v1/users/1234 + next.ServeHTTP(w, r) + }) + } + + func enforceJSON(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Content-Type") != "application/json" { + http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType) + return + } + next.ServeHTTP(w, r) + }) + } +``` + +See how we are using `logRequest(enforceJSON(mux))` instead of `wrap(mux)`? Now every incoming HTTP request will be logged and then checked for `Content-Type` before being passed onto the handler. + + +A cleaner way to chain multiple handlers is writing a single `wrap` middleware and chain all the middlewares inside `wrap`: + +```go + func wrap(handler http.Handler) http.Handler { + handler = enforceJSON(handler) + handler = logRequest(handler) + return handler + } +``` + +And then instead of: +```go + http.ListenAndServe(":8080", logRequest(enforceJSON(mux))) +``` + +We can use: +```go + http.ListenAndServe(":8080", wrap(mux)) +``` + + +----------- + + +That's all on middlewares in golang today. Hope it was useful with your understanding on middlewares or how to write them. \ No newline at end of file diff --git a/content/posts/writing-your-own-reverse-proxy-using-golang.md b/content/posts/writing-your-own-reverse-proxy-using-golang.md new file mode 100644 index 0000000..1648b74 --- /dev/null +++ b/content/posts/writing-your-own-reverse-proxy-using-golang.md @@ -0,0 +1,140 @@ ++++ +draft = false +date = 2021-10-12T22:05:04+05:00 +title = "Writing your own Reverse Proxy server using Golang" +description = "" +slug = "" +authors = ["Basit Ali"] +tags = ["golang", "reverse-proxy", "proxy", "go"] +categories = [] +externalLink = "" +series = [] ++++ + +Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. + + +Let us first start with defining Reverse Proxy and its common uses. + + +## Reverse Proxy + + +A `Reverse Proxy` is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. It is commonly used for: + + +* **Load Balancing –** It can distribute the load across multiple available backend servers in such manner that maximizes speed and capacity utilization while ensuring no one server is overloaded, which can degrade performance. + +* **Security –** By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks. + +* **Caching –** It can cache content to serve, and you can deploy regional proxies to cache content related to specific regions. + +* **TLS Termination –** We can use the reverse proxy to terminate the SSL/TLS connection with the clients in cases where backend servers are being hosted on the same secure VPC network, and it's ok to let the `reverse proxy` <-> `backend server` connection insecure. + +* **More –** Literally, there are a lot more use cases that can take leverage of reverse proxies, that I leave for you to explore. + + +## Personal Use Cases + + +Some common use cases I personally use `reverse proxy` server for are: + +* **TLS Termination –** Lets say I have multiple servers running on the same VPC network, each has it's own copy of the `TLS certificate` issued to same domain name, it makes sense to let the `reverse proxy` handle the TLS handshake and terminate the secure connection and forward it insecurely to appropriate backend server on the same VPC isolated from public reach, now instead of having `TLS certs` on every backend server you can have them on proxy only. + +* **Single VPS Dev Environment –** I have multiple backend servers for a single project, each with separate responsibilities, that I need to deploy but the servers would sit ideal 99% of the time I don't want to spin up multiple VPS for each for a dev environment, which would cost me money, also I don't want to explicitly mention the `port numbers` on the client side to have the servers run on the same VPS. To solve this, I can run all the backend servers and `reverse proxy` on a single VPS, and have the requests proxied to servers running on different ports. + + +Also sometimes for `Authorization`, `Caching` or implementing a feature like `Request Limit` per client. + + +## Let's Code + + +Enough with the uses, lets jump over to implementation. You are probably already familiar with Go standard library's `net/http` package, there's also a utility package for it you might have or might not have used, that is `net/http/httputil`. We'll be using this utility package because it has the type `ReverseProxy` defined which makes writing a reverse proxy so simple using Go. + +### Conditions + +Let's define some condition based on which we'll be forwarding the requests to appropriate server. For this tutorial lets stick to those conditions being the domain name or host of the requests: + +1. If request came on host `sub1.xyz.com`, forward to `localhost:8080`. +2. If request came on host `sub2.xyz.com`, forward to `localhost:8181`. +2. If request came from an unknown host, forward to `localhost:8888`. + +### `main.go` + +Now lets create a `main.go` file, which will do the following: + +```go + package main + + import "net/http" + + func main() { + http.HandleFunc("/", proxy) + if err := http.ListenAndServe(":4433", nil); err != nil { + panic(err) + } + } + + func proxy(w http.ResponseWriter, r *http.Request) { + // We will get to this later ... + } +``` + + +Now that we have a basic server in place, let's write our conditions for `reverse proxy` and use it to forward requests inside our `proxy` handler. + +```go + package main + + import ( + "net/http" + "net/http/httputil" + "net/url" + "strings" + ) + + func main() { + http.HandleFunc("/", proxy) + if err := http.ListenAndServe(":4433", nil); err != nil { + panic(err) + } + } + + func proxy(w http.ResponseWriter, r *http.Request) { + if strings.HasSuffix(r.Host, "://sub1.xyz.com") { // forward requests from sub1.xyz.com to localhost:8080 + if url, err := url.Parse("http://localhost:8080"); err == nil { + proxy := httputil.NewSingleHostReverseProxy(url) + proxy.ServeHTTP(w, r) + } + } else if strings.HasSuffix(r.Host, "://sub2.xyz.com") { // forward requests from sub2.xyz.com to localhost:8181 + if url, err := url.Parse("http://localhost:8181"); err == nil { + proxy := httputil.NewSingleHostReverseProxy(url) + proxy.ServeHTTP(w, r) + } + } else { // forward requests from unknown host to localhost:8888 + if url, err := url.Parse("http://localhost:8888"); err == nil { + proxy := httputil.NewSingleHostReverseProxy(url) + proxy.ServeHTTP(w, r) + } + } + } +``` + +The `httputil`'s `NewSingleHostReverseProxy(url)` function returns a new `ReverseProxy` that routes requests to `url` provided. And that's all, or what minimal we need to run a reverse proxy based on conditions we defined. + + +But there are many ways we can refactor this code, starting from using predefined `proxy` objects instead of creating a new one on each request. Or I prefer a map `map[string]*httputil.ReverseProxy` which maps hosts to proxies, so we can use the map to check if a proxy exists for host then use it, else use the default one. I'll leave the refactoring to anyone following this tutorial to keep it short. + + +## Next Steps + +Though it is pretty simple to write a `reverse proxy` using Go's standard library, but it's missing a lot of good stuff that comes with `nginx` or other solutions available. So you can start by implementing some of them into your own `reverse proxy` that is if the available solutions aren't feasible and you are having to develop your own, like: + +* Caching +* Logging +* Protocol Support (HTTP, HTTPS, HTTP/1.1, HTTP/2, ...) +* Rate Limit +* TLS Support +* Load Balancing +* ... \ No newline at end of file diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..93fb369 --- /dev/null +++ b/firebase.json @@ -0,0 +1,16 @@ +{ + "hosting": { + "public": "public", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/public/about/index.html b/public/about/index.html new file mode 100644 index 0000000..d542bef --- /dev/null +++ b/public/about/index.html @@ -0,0 +1,130 @@ + + + + + + + + + + + + About | Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+ +

Hi, I’m Basit Ali. I’m a software developer specializing in Java, Go and Android.

+

Previously I’ve worked with many startups including telehealth, trivia games, logistics and more. Right now I’m working on providing video conferencing and other VoIP solutions using WebRTC, Golang and other cool technologies.

+

I generally work with Go and Java for backend, React, Android, Git, Postgres and Linux, the technologies, especially databases can change depending on the needs of the project.

+

You can contact me for any short-term consultancy projects.

+ + +
+
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/categories/index.html b/public/categories/index.html new file mode 100644 index 0000000..3678a9d --- /dev/null +++ b/public/categories/index.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+ +
+ +
+ No categories +
+ +
+
    + +
+
+
+ +
+
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/categories/index.xml b/public/categories/index.xml new file mode 100644 index 0000000..6039d4d --- /dev/null +++ b/public/categories/index.xml @@ -0,0 +1,11 @@ + + + + Categories on Basit's Blog + https://blog.rjbasitali.com/categories/ + Recent content in Categories on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + + diff --git a/public/contact/index.html b/public/contact/index.html new file mode 100644 index 0000000..9a76c09 --- /dev/null +++ b/public/contact/index.html @@ -0,0 +1,126 @@ + + + + + + + + + + + + Contact | Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+ +

If you’ve got any questions, suggestions or would like to discuss a project then email me at rjbasitali@gmail.com. I’d be happy to hear from you.

+

You can also find me on LinkedIn, Github and Instagram.

+ + +
+
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/css/styles.94f653e9e151e28067a7c5dbbc4600cbd5a3c721e79faaf971e523c40f3b249b8e4f20bb57810dfffa8d559ca5c140fd56eb4cd9c0853113ad08e66afdb08bdd.css b/public/css/styles.94f653e9e151e28067a7c5dbbc4600cbd5a3c721e79faaf971e523c40f3b249b8e4f20bb57810dfffa8d559ca5c140fd56eb4cd9c0853113ad08e66afdb08bdd.css new file mode 100644 index 0000000..2324144 --- /dev/null +++ b/public/css/styles.94f653e9e151e28067a7c5dbbc4600cbd5a3c721e79faaf971e523c40f3b249b8e4f20bb57810dfffa8d559ca5c140fd56eb4cd9c0853113ad08e66afdb08bdd.css @@ -0,0 +1,3 @@ +.inline{display:inline}.block{display:block}.inline-block{display:inline-block}.table{display:table}.table-cell{display:table-cell}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.left{float:left}.right{float:right}.fit{max-width:100%}.truncate{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.max-width-1{max-width:24rem}.max-width-2{max-width:32rem}.max-width-3{max-width:48rem}.max-width-4{max-width:64rem}.border-box{box-sizing:border-box}.m0{margin:0}.mt0{margin-top:0}.mr0{margin-right:0}.mb0{margin-bottom:0}.ml0{margin-left:0}.mx0{margin-right:0;margin-left:0}.my0{margin-top:0;margin-bottom:0}.m1{margin:.5rem}.mt1{margin-top:.5rem}.mr1{margin-right:.5rem}.mb1{margin-bottom:.5rem}.ml1{margin-left:.5rem}.mx1{margin-right:.5rem;margin-left:.5rem}.my1{margin-top:.5rem;margin-bottom:.5rem}.m2{margin:1rem}.mt2{margin-top:1rem}.mr2{margin-right:1rem}.mb2{margin-bottom:1rem}.ml2{margin-left:1rem}.mx2{margin-right:1rem;margin-left:1rem}.my2{margin-top:1rem;margin-bottom:1rem}.m3{margin:2rem}.mt3{margin-top:2rem}.mr3{margin-right:2rem}.mb3{margin-bottom:2rem}.ml3{margin-left:2rem}.mx3{margin-right:2rem;margin-left:2rem}.my3{margin-top:2rem;margin-bottom:2rem}.m4{margin:4rem}.mt4{margin-top:4rem}.mr4{margin-right:4rem}.mb4{margin-bottom:4rem}.ml4{margin-left:4rem}.mx4{margin-right:4rem;margin-left:4rem}.my4{margin-top:4rem;margin-bottom:4rem}.mxn1{margin-right:-.5rem;margin-left:-.5rem}.mxn2{margin-right:-1rem;margin-left:-1rem}.mxn3{margin-right:-2rem;margin-left:-2rem}.mxn4{margin-right:-4rem;margin-left:-4rem}.ml-auto{margin-left:auto}.mr-auto{margin-right:auto}.mx-auto{margin-right:auto;margin-left:auto}.p0{padding:0}.pt0{padding-top:0}.pr0{padding-right:0}.pb0{padding-bottom:0}.pl0{padding-left:0}.px0{padding-right:0;padding-left:0}.py0{padding-top:0;padding-bottom:0}.p1{padding:.5rem}.pt1{padding-top:.5rem}.pr1{padding-right:.5rem}.pb1{padding-bottom:.5rem}.pl1{padding-left:.5rem}.py1{padding-top:.5rem;padding-bottom:.5rem}.px1{padding-right:.5rem;padding-left:.5rem}.p2{padding:1rem}.pt2{padding-top:1rem}.pr2{padding-right:1rem}.pb2{padding-bottom:1rem}.pl2{padding-left:1rem}.py2{padding-top:1rem;padding-bottom:1rem}.px2{padding-right:1rem;padding-left:1rem}.p3{padding:2rem}.pt3{padding-top:2rem}.pr3{padding-right:2rem}.pb3{padding-bottom:2rem}.pl3{padding-left:2rem}.py3{padding-top:2rem;padding-bottom:2rem}.px3{padding-right:2rem;padding-left:2rem}.p4{padding:4rem}.pt4{padding-top:4rem}.pr4{padding-right:4rem}.pb4{padding-bottom:4rem}.pl4{padding-left:4rem}.py4{padding-top:4rem;padding-bottom:4rem}.px4{padding-right:4rem;padding-left:4rem}h1,.h1{display:block;margin-top:3rem;margin-bottom:1rem;color:#2bbc8a;letter-spacing:.01em;font-weight:700;font-style:normal;font-size:1.5em;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h2,.h2{position:relative;display:block;margin-top:2rem;margin-bottom:.5rem;color:#383838;text-transform:none;letter-spacing:normal;font-weight:bold;font-size:1rem}h3{color:#383838;text-decoration:underline;font-weight:bold;font-size:.9rem}h4 h5 h6{display:inline;text-decoration:none;color:#8c8c8c;font-weight:bold;font-size:.9rem}h3 h4 h5 h6{margin-top:.9rem;margin-bottom:.5rem}hr{border:0.5px dashed #8c8c8c;opacity:.5;margin:0;margin-top:20px;margin-bottom:20px}strong{font-weight:bold}em cite{font-style:italic}sup sub{position:relative;vertical-align:baseline;font-size:.75em;line-height:0}sup{top:-.5em}sub{bottom:-.2em}small{font-size:.85em}acronym abbr{border-bottom:1px dotted}ul ol dl{line-height:1.725}ul ul,ol ul,ul ol,ol ol{margin-top:0;margin-bottom:0}ol{list-style:decimal}dt{font-weight:bold}table{width:100%;border-collapse:collapse;text-align:left;font-size:12px;overflow:auto;display:block}th{padding:8px;border-bottom:1px dashed #666;color:#383838;font-weight:bold;font-size:13px}td{padding:0 8px;border-bottom:none}@font-face{font-style:normal;font-family:"JetBrains Mono";font-display:swap;src:local("JetBrains Mono"),local("JetBrains-Mono"),url("../lib/JetBrainsMono/web/woff2/JetBrainsMono-Regular.woff2") format("woff2"),url("../lib/JetBrainsMono/web/woff/JetBrainsMono-Regular.woff") format("woff"),url("../lib/JetBrainsMono/web/eot/JetBrainsMono-Regular.eot") format("embedded-opentype"),url("../lib/JetBrainsMono/ttf/JetBrainsMono-Regular.ttf") format("truetype")}*,*:before,*:after{box-sizing:border-box}html{margin:0;padding:0;height:100%;border-top:2px solid #383838;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0;height:100%;background-color:#fff;color:#383838;font-display:swap;font-weight:400;font-size:14px;font-family:"JetBrains Mono",monospace;line-height:1.725;text-rendering:geometricPrecision;flex:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.content{position:relative;display:flex;flex-direction:column;min-height:100%;overflow-wrap:break-word}.content p{hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;-webkit-hyphens:auto}.content code{hyphens:manual;-moz-hyphens:manual;-ms-hyphens:manual;-webkit-hyphens:manual}.content a{color:#383838;text-decoration:none;background-image:linear-gradient(transparent, transparent 5px, #383838 5px, #383838);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.content a:hover{background-image:linear-gradient(transparent, transparent 4px, #d480aa 4px, #d480aa)}.content a.icon{background:none}.content a.icon:hover{color:#d480aa}.content h1 a,.content .h1 a,.content h2 a,.content h3 a,.content h4 a,.content h5 a,.content h6 a{background:none;color:inherit;text-decoration:none}.content h1 a:hover,.content .h1 a:hover,.content h2 a:hover,.content h3 a:hover,.content h4 a:hover,.content h5 a:hover,.content h6 a:hover{background-image:linear-gradient(transparent, transparent 6px, #d480aa 6px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.content h6 a{background:none;color:inherit;text-decoration:none}.content h6 a:hover{background-image:linear-gradient(transparent, transparent 6px, #d480aa 6px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}@media (min-width: 540px){.image-wrap{flex-direction:row;margin-bottom:2rem}.image-wrap .image-block{flex:1 0 35%;margin-right:2rem}.image-wrap p{flex:1 0 65%}}.max-width{max-width:48rem}@media (max-width: 480px){.px3{padding-right:1rem;padding-left:1rem}.my4{margin-top:2rem;margin-bottom:2rem}}@media (min-width: 480px){p{text-align:justify}}#header{margin:0 auto 2rem;width:100%}#header h1,#header .h1{margin-top:0;margin-bottom:0;color:#383838;letter-spacing:.01em;font-weight:700;font-style:normal;font-size:1.5rem;line-height:2rem;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}#header a{background:none;color:inherit;text-decoration:none}#header #logo{display:inline-block;float:left;margin-right:20px;width:50px;height:50px;border-radius:5px;background-size:50px 50px;background-repeat:no-repeat;filter:grayscale(100%);-webkit-filter:grayscale(100%)}#header #nav{color:#2bbc8a;letter-spacing:.01em;font-weight:200;font-style:normal;font-size:.8rem}#header #nav ul{margin:0;padding:0;list-style-type:none;line-height:15px}#header #nav ul a{margin-right:15px;color:#2bbc8a}#header #nav ul a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#header #nav ul li{display:inline-block;margin-right:15px;border-right:1px dotted;border-color:#2bbc8a;vertical-align:middle}#header #nav ul .icon{display:none}#header #nav ul li:last-child{margin-right:0;border-right:0}#header #nav ul li:last-child a{margin-right:0}#header:hover #logo{filter:none;-webkit-filter:none}@media screen and (max-width: 480px){#header #title{display:table;margin-right:5rem;min-height:50px}#header #title h1{display:table-cell;vertical-align:middle}#header #nav ul a:hover{background:none}#header #nav ul li{display:none;border-right:0}#header #nav ul li.icon{position:absolute;top:77px;right:1rem;display:inline-block}#header #nav ul.responsive li{display:block}#header #nav li:not(:first-child){padding-top:1rem;padding-left:70px;font-size:1rem}}#header-post{position:fixed;top:2rem;right:0;display:inline-block;float:right;z-index:100}#header-post a{background:none;color:inherit;text-decoration:none}#header-post a.icon{background:none}#header-post a.icon:hover{color:#d480aa}#header-post nav ul{display:block;list-style-image:none;list-style-position:outside;list-style-type:none;padding-inline-start:40px}#header-post nav ul li{display:list-item;margin-right:0px}#header-post nav>ul{margin-block-end:1em;margin-block-start:1em}#header-post ul{display:inline-block;margin:0;padding:0;list-style-type:none}#header-post ul li{display:inline-block;margin-right:15px;vertical-align:middle}#header-post ul li:last-child{margin-right:0}#header-post #menu-icon{float:right;margin-right:2rem;margin-left:15px}#header-post #menu-icon:hover{color:#2bbc8a}#header-post #menu-icon-tablet{float:right;margin-right:2rem;margin-left:15px}#header-post #menu-icon-tablet:hover{color:#2bbc8a}#header-post #top-icon-tablet{position:fixed;right:2rem;bottom:2rem;margin-right:2rem;margin-left:15px}#header-post #top-icon-tablet:hover{color:#2bbc8a}#header-post .active{color:#2bbc8a}#header-post #menu{visibility:hidden;margin-right:2rem}#header-post #nav{color:#2bbc8a;letter-spacing:.01em;font-weight:200;font-style:normal;font-size:.8rem}#header-post #nav ul{line-height:15px}#header-post #nav ul a{margin-right:15px;color:#2bbc8a}#header-post #nav ul a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#header-post #nav ul li{border-right:1px dotted #2bbc8a}#header-post #nav ul li:last-child{margin-right:0;border-right:0}#header-post #nav ul li:last-child a{margin-right:0}#header-post #actions{float:right;margin-top:2rem;margin-right:2rem;width:100%;text-align:right}#header-post #actions ul{display:block}#header-post #actions .info{display:block;font-style:italic}#header-post #share{clear:both;padding-top:1rem;padding-right:2rem;text-align:right}#header-post #share li{display:block;margin:0}#header-post #toc{float:right;clear:both;overflow:auto;margin-top:1rem;padding-right:2rem;max-width:20em;max-height:calc(95vh - 7rem);text-align:right}#header-post #toc a:hover{color:#d480aa}#header-post #toc nav>ul>li{color:#383838;font-size:.8rem}#header-post #toc nav>ul>li:before{color:#2bbc8a;content:"#";margin-right:8px}#header-post #toc nav>ul>li>ul>li{color:#666;font-size:.7rem}#header-post #toc nav>ul>li>ul>li:before{color:#2bbc8a;content:"·";font-weight:bold;margin-right:3px}#header-post #toc nav>ul>li>ul>li>ul>li{color:#333;font-size:.4rem}#header-post #toc .toc-level-5{display:none}#header-post #toc .toc-level-6{display:none}#header-post #toc .toc-number{display:none}@media screen and (max-width: 500px){#header-post{display:none}}@media screen and (max-width: 900px){#header-post #menu-icon{display:none}#header-post #actions{display:none}}@media screen and (max-width: 1199px){#header-post #toc{display:none}}@media screen and (min-width: 900px){#header-post #menu-icon-tablet{display:none !important}#header-post #top-icon-tablet{display:none !important}}@media screen and (min-width: 1199px){#header-post #actions{width:auto}#header-post #actions ul{display:inline-block;float:right}#header-post #actions .info{display:inline;float:left;margin-right:2rem;font-style:italic}}#footer-post{position:fixed;right:0;bottom:0;left:0;z-index:5000000;width:100%;border-top:1px solid #666;background:#fafafa;transition:opacity .2s}#footer-post a{background:none;color:inherit;text-decoration:none}#footer-post a.icon{background:none}#footer-post a.icon:hover{color:#d480aa}#footer-post #nav-footer{padding-right:1rem;padding-left:1rem;background:#e6e6e6;text-align:center}#footer-post #nav-footer a{color:#2bbc8a;font-size:1em}#footer-post #nav-footer a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#footer-post #nav-footer ul{display:table;margin:0;padding:0;width:100%;list-style-type:none}#footer-post #nav-footer ul li{display:inline-table;padding:10px;width:20%;vertical-align:middle}#footer-post #actions-footer{overflow:auto;margin-top:1rem;margin-bottom:1rem;padding-right:1rem;padding-left:1rem;width:100%;text-align:center;white-space:nowrap}#footer-post #actions-footer a{display:inline-block;padding-left:1rem;color:#2bbc8a}#footer-post #share-footer{padding-right:1rem;padding-left:1rem;background:#e6e6e6;text-align:center}#footer-post #share-footer ul{display:table;margin:0;padding:0;width:100%;list-style-type:none}#footer-post #share-footer ul li{display:inline-table;padding:10px;width:20%;vertical-align:middle}#footer-post #toc-footer{clear:both;padding-top:1rem;padding-bottom:1rem;background:#e6e6e6;text-align:left}#footer-post #toc-footer #TableOfContents ul{margin:0;padding-left:20px;list-style-type:none}#footer-post #toc-footer #TableOfContents ul li{line-height:30px}#footer-post #toc-footer a:hover{color:#d480aa}#footer-post #toc-footer #TableOfContents>ul>li{color:#383838;font-size:.8rem}#footer-post #toc-footer #TableOfContents>ul>li:before{color:#2bbc8a;content:"#";margin-right:8px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li{color:#666;font-size:.7rem;line-height:15px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li:before{color:#2bbc8a;content:"·";font-weight:bold;margin-right:3px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li>ul>li{display:none}@media screen and (min-width: 500px){#footer-post-container{display:none}}.post-list{padding:0}.post-list .post-item{margin-bottom:1rem;margin-left:0;list-style-type:none}.post-list .post-item .meta{display:block;margin-right:16px;min-width:100px;color:#666;font-size:14px}@media (min-width: 480px){.post-list .post-item{display:flex;margin-bottom:5px}.post-list .post-item .meta{text-align:left}}.project-list{padding:0;list-style:none}.project-list .project-item{margin-bottom:5px}.project-list .project-item p{display:inline}article header .posttitle{margin-top:0;margin-bottom:0;text-transform:none;font-size:1.5em;line-height:1.25}article header .meta{margin-top:0;margin-bottom:1rem}article header .meta *{color:#8c8c8c;font-size:.85rem}article header .author{text-transform:uppercase;letter-spacing:.01em;font-weight:700}article header .postdate{display:inline}article .content h2:before{position:absolute;top:-4px;left:-1rem;color:#2bbc8a;content:"#";font-weight:bold;font-size:1.2rem}article .content img,article .content video{display:block;margin:auto;max-width:100%;height:auto}article .content img .video-container,article .content video .video-container{position:relative;overflow:hidden;padding-top:56.25% e;height:0}article .content img .video-container iframe,article .content img .video-container object,article .content img .video-container embed,article .content video .video-container iframe,article .content video .video-container object,article .content video .video-container embed{position:absolute;top:0;left:0;margin-top:0;width:100%;height:100%}article .content img blockquote,article .content video blockquote{margin:1rem 10px;padding:.5em 10px;background:inherit;color:#2bbc8a;quotes:"\201C" "\201D" "\2018" "\2019";font-weight:bold}article .content img blockquote p,article .content video blockquote p{margin:0}article .content img blockquote:before,article .content video blockquote:before{margin-right:.25em;color:#2bbc8a;content:"\201C";vertical-align:-.4em;font-size:2em;line-height:.1em}article .content img blockquote footer,article .content video blockquote footer{margin:line-height 0;color:#666;font-size:11px}article .content img blockquote footer a,article .content video blockquote footer a{background-image:linear-gradient(transparent, transparent 5px, #666 5px, #666);color:#666}article .content img blockquote footer a:hover,article .content video blockquote footer a:hover{background-image:linear-gradient(transparent, transparent 4px, #999 4px, #999);color:#999}article .content img blockquote footer cite:before,article .content video blockquote footer cite:before{padding:0 .5em;content:"—"}article .content img .pullquote,article .content video .pullquote{margin:0;width:45%;text-align:left}article .content img .pullquote.left,article .content video .pullquote.left{margin-right:1em;margin-left:.5em}article .content img .pullquote.right,article .content video .pullquote.right{margin-right:.5em;margin-left:1em}article .content img .caption,article .content video .caption{position:relative;display:block;margin-top:.5em;color:#666;text-align:center;font-size:.9em}.posttitle{text-transform:none;font-size:1.5em;line-height:1.25}.article-tag .tag-link:before{content:"#";background-image:linear-gradient(transparent, transparent 10px, #d480aa 10px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.article-category .category-link{background-image:linear-gradient(transparent, transparent 10px, #d480aa 10px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}@media (min-width: 480px){.article-read-time,.article-tag,.article-category{display:inline}.article-read-time:before,.article-tag:before,.article-category:before{content:"|"}}#archive .post-list{padding:0}#archive .post-list .post-item{margin-bottom:1rem;margin-left:0;list-style-type:none}#archive .post-list .post-item .meta{display:block;margin-right:16px;min-width:100px;color:#666;font-size:14px}@media (min-width: 480px){#archive .post-list .post-item{display:flex;margin-bottom:5px;margin-left:1rem}#archive .post-list .post-item .meta{text-align:left}}.blog-post-comments{margin-top:4rem}#footer{position:absolute;bottom:0;margin-bottom:10px;width:100%;color:#666;vertical-align:top;text-align:center;font-size:11px}#footer ul{margin:0;padding:0;list-style:none}#footer li{display:inline-block;margin-right:15px;border-right:1px solid;border-color:#666;vertical-align:middle}#footer li a{margin-right:15px}#footer li:last-child{margin-right:0;border-right:0}#footer li:last-child a{margin-right:0}#footer a{color:#666;text-decoration:underline;background-image:none}#footer a:hover{color:#999}#footer .footer-left{height:20px;vertical-align:middle;line-height:20px}@media (min-width: 39rem){#footer{display:flex;flex-flow:row wrap;justify-content:space-between;align-items:center;align-content:center;margin-bottom:20px}#footer .footer-left{align-self:flex-start;margin-right:20px}#footer .footer-right{align-self:flex-end}}.pagination{display:inline-block;margin-top:2rem;width:100%;text-align:center}.pagination .page-number{color:#383838;font-size:.8rem}.pagination a{padding:4px 6px;border-radius:5px;background-image:none;color:#383838;text-decoration:none}.pagination a:hover{background-image:none}.pagination a:hover:not(.active){color:#383838}.search-input{padding:4px 7px;width:100%;outline:none;border:solid 1px #8c8c8c;border-radius:5px;background-color:#fff;color:#383838;font-size:1.2rem;-webkit-border-radius:5px;-moz-border-radius:5px}.search-input:focus{border:solid 1px #2bbc8a}#search-result ul.search-result-list{padding:0;list-style-type:none}#search-result li{margin:2em auto}#search-result a.search-result-title{background-image:none;color:#383838;text-transform:capitalize;font-weight:bold;line-height:1.2}#search-result p.search-result{overflow:hidden;margin:.4em auto;max-height:13em;text-align:justify;font-size:.8em}#search-result em.search-keyword{border-bottom:1px dashed #d480aa;color:#d480aa;font-weight:bold}.search-no-result{display:none;padding-bottom:.5em;color:#383838}#tag-cloud .tag-cloud-title{color:#666}#tag-cloud .tag-cloud-tags{clear:both;text-align:center}#tag-cloud .tag-cloud-tags a{display:inline-block;margin:10px}.tooltipped{position:relative}.tooltipped::after{position:absolute;z-index:1000000;display:none;padding:.2em .5em;-webkit-font-smoothing:subpixel-antialiased;color:#fff;font-display:swap;font-weight:400;font-size:11.2px;font-family:"JetBrains Mono",monospace;line-height:1.725;text-rendering:geometricPrecision;text-align:center;word-wrap:break-word;white-space:pre;content:attr(aria-label);background:#383838;border-radius:3px;opacity:0}.tooltipped::before{position:absolute;z-index:1000001;display:none;width:0;height:0;color:#383838;pointer-events:none;content:'';border:6px solid transparent;opacity:0}@keyframes tooltip-appear{from{opacity:0}to{opacity:1}}.tooltipped:hover::before,.tooltipped:hover::after,.tooltipped:active::before,.tooltipped:active::after,.tooltipped:focus::before,.tooltipped:focus::after{display:inline-block;text-decoration:none;animation-name:tooltip-appear;animation-duration:0.1s;animation-fill-mode:forwards;animation-timing-function:ease-in}.tooltipped-s::after,.tooltipped-sw::after{top:100%;right:50%;margin-top:6px}.tooltipped-s::before,.tooltipped-sw::before{top:auto;right:50%;bottom:-7px;margin-right:-6px;border-bottom-color:#383838}.tooltipped-sw::after{margin-right:-16px}.tooltipped-s::after{transform:translateX(50%)}#categories .category-list-title{color:#666}#categories .category-list .category-list-item .category-list-count{color:#666}#categories .category-list .category-list-item .category-list-count:before{content:" ("}#categories .category-list .category-list-item .category-list-count:after{content:")"}pre{overflow-x:auto;padding:15px 15px 10px 15px;border:1px dotted #666;border-radius:2px;-webkit-border-radius:2px;font-size:13px;font-family:"JetBrains Mono",monospace;line-height:22px;position:relative}pre .code-copy-btn{position:absolute;top:0;right:0;border:0;border-radius:0 2px;padding:0;font-family:"JetBrains Mono", monospace;font-weight:800;font-size:0.9em;line-height:1.7;color:#fff;background-color:#8c8c8c;min-width:60px;text-align:center;cursor:pointer;letter-spacing:0em}pre .code-copy-btn:hover{background-color:#666;color:#2bbc8a}pre code{display:block;padding:0;border:none}code{font-family:"JetBrains Mono",monospace;padding:0 5px;border:1px dotted #666;border-radius:2px;-webkit-border-radius:2px}.highlight>div{border-radius:2px;-webkit-border-radius:2px}.highlight pre{border:none;background:none}.highlight table pre{margin-top:0}.highlight table td:first-child pre{padding-right:0}.highlight table td:last-child pre{padding-left:0} + +/*# sourceMappingURL=styles.css.map */ \ No newline at end of file diff --git a/public/css/styles.css.map b/public/css/styles.css.map new file mode 100644 index 0000000..43b7e9c --- /dev/null +++ b/public/css/styles.css.map @@ -0,0 +1,51 @@ +{ + "version": 3, + "file": "styles.css", + "sourceRoot": "C:/Users/Basit/Desktop/Me/personal-blog", + "sources": [ + "themes/cactus/assets/scss/style.scss", + "themes/cactus/assets/scss/_variables.scss", + "themes/cactus/assets/scss/colors/white.scss", + "themes/cactus/assets/scss/_util.scss", + "themes/cactus/assets/scss/_mixins.scss", + "themes/cactus/assets/scss/_extend.scss", + "themes/cactus/assets/scss/_fonts.scss", + "themes/cactus/assets/scss/partial/header.scss", + "themes/cactus/assets/scss/partial/post/actions_desktop.scss", + "themes/cactus/assets/scss/partial/post/actions_mobile.scss", + "themes/cactus/assets/scss/partial/index.scss", + "themes/cactus/assets/scss/partial/article.scss", + "themes/cactus/assets/scss/partial/archive.scss", + "themes/cactus/assets/scss/partial/comments.scss", + "themes/cactus/assets/scss/partial/footer.scss", + "themes/cactus/assets/scss/partial/pagination.scss", + "themes/cactus/assets/scss/partial/search.scss", + "themes/cactus/assets/scss/partial/tags.scss", + "themes/cactus/assets/scss/partial/tooltip.scss", + "themes/cactus/assets/scss/partial/categories.scss" + ], + "sourcesContent": [ + "@import \"variables\";\r\n@import \"colors/white\";\r\n@import \"util\";\r\n@import \"mixins\";\r\n@import \"extend\";\r\n@import \"fonts\";\r\n\r\n// global-reset()\r\n\r\n*,\r\n*:before,\r\n*:after {\r\n box-sizing: border-box;\r\n}\r\nhtml {\r\n margin: 0;\r\n padding: 0;\r\n height: 100%;\r\n border-top: 2px solid $color-text;\r\n -webkit-text-size-adjust: 100%;\r\n -ms-text-size-adjust: 100%;\r\n}\r\nbody {\r\n margin: 0;\r\n height: 100%;\r\n background-color: $color-background;\r\n color: $color-text;\r\n font-display: swap;\r\n font-weight: 400;\r\n font-size: $font-size;\r\n font-family: $font-family-body;\r\n line-height: $line-height;\r\n text-rendering: geometricPrecision;\r\n flex: 1;\r\n\r\n @include antialias();\r\n\r\n @extend $base-style !optional;\r\n}\r\n.content {\r\n position: relative;\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n overflow-wrap: break-word;\r\n\r\n p {\r\n @include hyphens(auto);\r\n }\r\n code {\r\n @include hyphens(manual);\r\n }\r\n a {\r\n color: $color-text;\r\n text-decoration: none;\r\n\r\n @include underline(5px, $color-text);\r\n\r\n &:hover {\r\n background-image: linear-gradient(transparent, transparent 4px, $color-link 4px, $color-link);\r\n }\r\n }\r\n a.icon {\r\n background: none;\r\n\r\n &:hover {\r\n color: $color-link;\r\n }\r\n }\r\n h1 a,\r\n .h1 a,\r\n h2 a,\r\n h3 a,\r\n h4 a,\r\n h5 a,\r\n h6 a {\r\n background: none;\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n h1 a:hover,\r\n .h1 a:hover,\r\n h2 a:hover,\r\n h3 a:hover,\r\n h4 a:hover,\r\n h5 a:hover,\r\n h6 a:hover {\r\n @include underline(6px, $color-link);\r\n }\r\n h6 {\r\n a {\r\n background: none;\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n }\r\n h6 {\r\n a:hover {\r\n @include underline(6px, $color-link);\r\n }\r\n }\r\n}\r\n@media (min-width: 540px) {\r\n .image-wrap {\r\n flex-direction: row;\r\n margin-bottom: 2rem;\r\n\r\n .image-block {\r\n flex: 1 0 35%;\r\n margin-right: 2rem;\r\n }\r\n p {\r\n flex: 1 0 65%;\r\n }\r\n }\r\n}\r\n.max-width {\r\n max-width: $page-width;\r\n}\r\n@media (max-width: 480px) { // smaller margins at smaller screen widths\r\n .px3 {\r\n padding-right: 1rem;\r\n padding-left: 1rem;\r\n }\r\n .my4 {\r\n margin-top: 2rem;\r\n margin-bottom: 2rem;\r\n }\r\n}\r\n\r\n@media (min-width: 480px) {\r\n p {\r\n text-align: justify;\r\n }\r\n}\r\n\r\n@import \"partial/header\";\r\n@import \"partial/post/actions_desktop\";\r\n@import \"partial/post/actions_mobile\";\r\n@import \"partial/index\";\r\n@import \"partial/article\";\r\n@import \"partial/archive\";\r\n@import \"partial/comments\";\r\n@import \"partial/footer\";\r\n@import \"partial/pagination\";\r\n@import \"partial/search\";\r\n@import \"partial/tags\";\r\n@import \"partial/tooltip\";\r\n@import \"partial/categories\";\r\n\r\npre {\r\n overflow-x: auto;\r\n padding: 15px 15px 10px 15px;\r\n border: 1px dotted $color-border;\r\n border-radius: 2px;\r\n -webkit-border-radius: 2px;\r\n font-size: 13px;\r\n font-family: $font-family-mono;\r\n line-height: 22px;\r\n position: relative;\r\n\r\n .code-copy-btn {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n border: 0;\r\n border-radius: 0 2px;\r\n padding: 0;\r\n font-family: \"JetBrains Mono\", monospace;\r\n font-weight: 800;\r\n font-size: 0.9em;\r\n line-height: 1.7;\r\n color: #fff;\r\n background-color: #8c8c8c;\r\n min-width: 60px;\r\n text-align: center;\r\n cursor: pointer;\r\n letter-spacing: 0em;\r\n }\r\n\r\n .code-copy-btn:hover {\r\n background-color: #666;\r\n color: #2bbc8a;\r\n }\r\n\r\n code {\r\n display: block;\r\n padding: 0;\r\n border: none;\r\n }\r\n}\r\n\r\ncode {\r\n font-family: $font-family-mono;\r\n padding: 0 5px;\r\n border: 1px dotted $color-border;\r\n border-radius: 2px;\r\n -webkit-border-radius: 2px;\r\n}\r\n\r\n.highlight {\r\n\r\n & > div {\r\n border-radius: 2px;\r\n -webkit-border-radius: 2px;\r\n }\r\n\r\n pre {\r\n border: none;\r\n background: none;\r\n }\r\n\r\n table {\r\n\r\n pre {\r\n margin-top: 0;\r\n }\r\n\r\n td:first-child {\r\n pre {\r\n padding-right: 0;\r\n }\r\n }\r\n\r\n td:last-child {\r\n pre {\r\n padding-left: 0;\r\n }\r\n }\r\n }\r\n}", + "// Fonts\r\n$font-family-body: \"JetBrains Mono\", monospace;\r\n$font-family-mono: \"JetBrains Mono\", monospace;\r\n$font-family-tt: \"Inconsolata\", monospace;\r\n$font-size: 14px;\r\n$line-height: 1.725;\r\n$page-width: 48rem;\r\n// Logo\r\n$logo-width: 50px;\r\n$logo-height: 50px;\r\n$logo-grayout: true;\r\n// Colors\r\n$colors: \"dark\" // white dark light classic", + "// by @sergodeeva (https://github.com/sergodeeva)\r\n$color-background: #FFFFFF;\r\n$color-footer-mobile-1: darken($color-background, 2%);\r\n$color-footer-mobile-2: darken($color-background, 10%);\r\n$color-background-code: darken($color-background, 2%);\r\n$color-border: #666;\r\n$color-meta: #666;\r\n$color-meta-code: lighten($color-meta, 10%);\r\n$color-link: rgba(212, 128, 170, 1);\r\n$color-text: #383838;\r\n$color-accent-3: #8c8c8c;\r\n$color-accent-2: #383838;\r\n$color-accent-1: #2bbc8a;\r\n$color-quote: #2bbc8a;", + "/* Basscss */\r\n.inline {\r\n display: inline;\r\n}\r\n.block {\r\n display: block;\r\n}\r\n.inline-block {\r\n display: inline-block;\r\n}\r\n.table {\r\n display: table;\r\n}\r\n.table-cell {\r\n display: table-cell;\r\n}\r\n.overflow-hidden {\r\n overflow: hidden;\r\n}\r\n.overflow-scroll {\r\n overflow: scroll;\r\n}\r\n.overflow-auto {\r\n overflow: auto;\r\n}\r\n.clearfix:before,\r\n.clearfix:after {\r\n display: table;\r\n content: \" \";\r\n}\r\n.clearfix:after {\r\n clear: both;\r\n}\r\n.left {\r\n float: left;\r\n}\r\n.right {\r\n float: right;\r\n}\r\n.fit {\r\n max-width: 100%;\r\n}\r\n.truncate {\r\n display: inline-block;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n.max-width-1 {\r\n max-width: 24rem;\r\n}\r\n.max-width-2 {\r\n max-width: 32rem;\r\n}\r\n.max-width-3 {\r\n max-width: 48rem;\r\n}\r\n.max-width-4 {\r\n max-width: 64rem;\r\n}\r\n.border-box {\r\n box-sizing: border-box;\r\n}\r\n.m0 {\r\n margin: 0;\r\n}\r\n.mt0 {\r\n margin-top: 0;\r\n}\r\n.mr0 {\r\n margin-right: 0;\r\n}\r\n.mb0 {\r\n margin-bottom: 0;\r\n}\r\n.ml0 {\r\n margin-left: 0;\r\n}\r\n.mx0 {\r\n margin-right: 0;\r\n margin-left: 0;\r\n}\r\n.my0 {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n.m1 {\r\n margin: .5rem;\r\n}\r\n.mt1 {\r\n margin-top: .5rem;\r\n}\r\n.mr1 {\r\n margin-right: .5rem;\r\n}\r\n.mb1 {\r\n margin-bottom: .5rem;\r\n}\r\n.ml1 {\r\n margin-left: .5rem;\r\n}\r\n.mx1 {\r\n margin-right: .5rem;\r\n margin-left: .5rem;\r\n}\r\n.my1 {\r\n margin-top: .5rem;\r\n margin-bottom: .5rem;\r\n}\r\n.m2 {\r\n margin: 1rem;\r\n}\r\n.mt2 {\r\n margin-top: 1rem;\r\n}\r\n.mr2 {\r\n margin-right: 1rem;\r\n}\r\n.mb2 {\r\n margin-bottom: 1rem;\r\n}\r\n.ml2 {\r\n margin-left: 1rem;\r\n}\r\n.mx2 {\r\n margin-right: 1rem;\r\n margin-left: 1rem;\r\n}\r\n.my2 {\r\n margin-top: 1rem;\r\n margin-bottom: 1rem;\r\n}\r\n.m3 {\r\n margin: 2rem;\r\n}\r\n.mt3 {\r\n margin-top: 2rem;\r\n}\r\n.mr3 {\r\n margin-right: 2rem;\r\n}\r\n.mb3 {\r\n margin-bottom: 2rem;\r\n}\r\n.ml3 {\r\n margin-left: 2rem;\r\n}\r\n.mx3 {\r\n margin-right: 2rem;\r\n margin-left: 2rem;\r\n}\r\n.my3 {\r\n margin-top: 2rem;\r\n margin-bottom: 2rem;\r\n}\r\n.m4 {\r\n margin: 4rem;\r\n}\r\n.mt4 {\r\n margin-top: 4rem;\r\n}\r\n.mr4 {\r\n margin-right: 4rem;\r\n}\r\n.mb4 {\r\n margin-bottom: 4rem;\r\n}\r\n.ml4 {\r\n margin-left: 4rem;\r\n}\r\n.mx4 {\r\n margin-right: 4rem;\r\n margin-left: 4rem;\r\n}\r\n.my4 {\r\n margin-top: 4rem;\r\n margin-bottom: 4rem;\r\n}\r\n.mxn1 {\r\n margin-right: -.5rem;\r\n margin-left: -.5rem;\r\n}\r\n.mxn2 {\r\n margin-right: -1rem;\r\n margin-left: -1rem;\r\n}\r\n.mxn3 {\r\n margin-right: -2rem;\r\n margin-left: -2rem;\r\n}\r\n.mxn4 {\r\n margin-right: -4rem;\r\n margin-left: -4rem;\r\n}\r\n.ml-auto {\r\n margin-left: auto;\r\n}\r\n.mr-auto {\r\n margin-right: auto;\r\n}\r\n.mx-auto {\r\n margin-right: auto;\r\n margin-left: auto;\r\n}\r\n.p0 {\r\n padding: 0;\r\n}\r\n.pt0 {\r\n padding-top: 0;\r\n}\r\n.pr0 {\r\n padding-right: 0;\r\n}\r\n.pb0 {\r\n padding-bottom: 0;\r\n}\r\n.pl0 {\r\n padding-left: 0;\r\n}\r\n.px0 {\r\n padding-right: 0;\r\n padding-left: 0;\r\n}\r\n.py0 {\r\n padding-top: 0;\r\n padding-bottom: 0;\r\n}\r\n.p1 {\r\n padding: .5rem;\r\n}\r\n.pt1 {\r\n padding-top: .5rem;\r\n}\r\n.pr1 {\r\n padding-right: .5rem;\r\n}\r\n.pb1 {\r\n padding-bottom: .5rem;\r\n}\r\n.pl1 {\r\n padding-left: .5rem;\r\n}\r\n.py1 {\r\n padding-top: .5rem;\r\n padding-bottom: .5rem;\r\n}\r\n.px1 {\r\n padding-right: .5rem;\r\n padding-left: .5rem;\r\n}\r\n.p2 {\r\n padding: 1rem;\r\n}\r\n.pt2 {\r\n padding-top: 1rem;\r\n}\r\n.pr2 {\r\n padding-right: 1rem;\r\n}\r\n.pb2 {\r\n padding-bottom: 1rem;\r\n}\r\n.pl2 {\r\n padding-left: 1rem;\r\n}\r\n.py2 {\r\n padding-top: 1rem;\r\n padding-bottom: 1rem;\r\n}\r\n.px2 {\r\n padding-right: 1rem;\r\n padding-left: 1rem;\r\n}\r\n.p3 {\r\n padding: 2rem;\r\n}\r\n.pt3 {\r\n padding-top: 2rem;\r\n}\r\n.pr3 {\r\n padding-right: 2rem;\r\n}\r\n.pb3 {\r\n padding-bottom: 2rem;\r\n}\r\n.pl3 {\r\n padding-left: 2rem;\r\n}\r\n.py3 {\r\n padding-top: 2rem;\r\n padding-bottom: 2rem;\r\n}\r\n.px3 {\r\n padding-right: 2rem;\r\n padding-left: 2rem;\r\n}\r\n.p4 {\r\n padding: 4rem;\r\n}\r\n.pt4 {\r\n padding-top: 4rem;\r\n}\r\n.pr4 {\r\n padding-right: 4rem;\r\n}\r\n.pb4 {\r\n padding-bottom: 4rem;\r\n}\r\n.pl4 {\r\n padding-left: 4rem;\r\n}\r\n.py4 {\r\n padding-top: 4rem;\r\n padding-bottom: 4rem;\r\n}\r\n.px4 {\r\n padding-right: 4rem;\r\n padding-left: 4rem;\r\n}", + "@mixin antialias() {\r\n -moz-osx-font-smoothing: grayscale;\r\n -webkit-font-smoothing: antialiased;\r\n}\r\n@mixin hyphens($value) {\r\n hyphens: $value;\r\n -moz-hyphens: $value;\r\n -ms-hyphens: $value;\r\n -webkit-hyphens: $value;\r\n}\r\n@mixin underline($size, $color) {\r\n background-image: linear-gradient(transparent, transparent $size, $color $size, $color);\r\n background-position: bottom;\r\n background-size: 100% 6px;\r\n background-repeat: repeat-x;\r\n}\r\n@mixin no-select() {\r\n user-select: none;\r\n -khtml-user-select: none;\r\n}", + "// $base-style\r\nh1,\r\n.h1 {\r\n display: block;\r\n margin-top: 3rem;\r\n margin-bottom: 1rem;\r\n color: $color-accent-1;\r\n letter-spacing: .01em;\r\n font-weight: 700;\r\n font-style: normal;\r\n font-size: 1.5em;\r\n\r\n @include antialias();\r\n}\r\nh2,\r\n.h2 {\r\n position: relative;\r\n display: block;\r\n margin-top: 2rem;\r\n margin-bottom: .5rem;\r\n color: $color-accent-2;\r\n text-transform: none;\r\n letter-spacing: normal;\r\n font-weight: bold;\r\n font-size: 1rem;\r\n}\r\nh3 {\r\n color: $color-accent-2;\r\n text-decoration: underline;\r\n font-weight: bold;\r\n font-size: .9rem;\r\n}\r\nh4\r\nh5\r\nh6 {\r\n display: inline;\r\n text-decoration: none;\r\n color: $color-accent-3;\r\n font-weight: bold;\r\n font-size: .9rem;\r\n}\r\nh3\r\nh4\r\nh5\r\nh6 {\r\n margin-top: .9rem;\r\n margin-bottom: .5rem;\r\n}\r\nhr {\r\n border: .5px dashed $color-accent-3;\r\n opacity: .5;\r\n margin: 0;\r\n margin-top: 20px;\r\n margin-bottom: 20px;\r\n}\r\nstrong {\r\n font-weight: bold;\r\n}\r\nem\r\ncite {\r\n font-style: italic;\r\n}\r\nsup\r\nsub {\r\n position: relative;\r\n vertical-align: baseline;\r\n font-size: .75em;\r\n line-height: 0;\r\n}\r\nsup {\r\n top: -.5em;\r\n}\r\nsub {\r\n bottom: -.2em;\r\n}\r\nsmall {\r\n font-size: .85em;\r\n}\r\nacronym\r\nabbr {\r\n border-bottom: 1px dotted;\r\n}\r\nul\r\nol\r\ndl {\r\n line-height: $line-height;\r\n}\r\nul ul,\r\nol ul,\r\nul ol,\r\nol ol {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\nol {\r\n list-style: decimal;\r\n}\r\ndt {\r\n font-weight: bold;\r\n}\r\ntable {\r\n width: 100%;\r\n border-collapse: collapse;\r\n text-align: left;\r\n font-size: $font-size - 2px;\r\n overflow: auto;\r\n display: block;\r\n}\r\nth {\r\n padding: 8px;\r\n border-bottom: 1px dashed $color-border;\r\n color: $color-accent-2;\r\n font-weight: bold;\r\n font-size: $font-size - 1px;\r\n}\r\ntd {\r\n padding: 0 8px;\r\n border-bottom: none;\r\n}", + "@font-face {\r\n font-style: normal;\r\n font-family: \"JetBrains Mono\";\r\n font-display: swap;\r\n src: local(\"JetBrains Mono\"), local(\"JetBrains-Mono\"), url(\"../lib/JetBrainsMono/web/woff2/JetBrainsMono-Regular.woff2\") format(\"woff2\"), url(\"../lib/JetBrainsMono/web/woff/JetBrainsMono-Regular.woff\") format(\"woff\"), url(\"../lib/JetBrainsMono/web/eot/JetBrainsMono-Regular.eot\") format(\"embedded-opentype\"), url(\"../lib/JetBrainsMono/ttf/JetBrainsMono-Regular.ttf\") format(\"truetype\");\r\n};", + "#header {\r\n margin: 0 auto 2rem;\r\n width: 100%;\r\n\r\n h1,\r\n .h1 {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n color: $color-text;\r\n letter-spacing: .01em;\r\n font-weight: 700;\r\n font-style: normal;\r\n font-size: 1.5rem;\r\n line-height: 2rem;\r\n\r\n @include antialias();\r\n }\r\n a {\r\n background: none;\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n #logo {\r\n display: inline-block;\r\n float: left;\r\n margin-right: 20px;\r\n width: $logo-width;\r\n height: $logo-height;\r\n border-radius: 5px;\r\n background-size: $logo-width $logo-height;\r\n background-repeat: no-repeat;\r\n @if $logo-grayout {\r\n filter: grayscale(100%);\r\n -webkit-filter: grayscale(100%);\r\n }\r\n }\r\n #nav {\r\n color: $color-accent-1;\r\n letter-spacing: .01em;\r\n font-weight: 200;\r\n font-style: normal;\r\n font-size: .8rem;\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n line-height: 15px;\r\n\r\n a {\r\n margin-right: 15px;\r\n color: $color-accent-1;\r\n }\r\n a:hover {\r\n @include underline(5px, $color-accent-1);\r\n }\r\n li {\r\n display: inline-block;\r\n margin-right: 15px;\r\n border-right: 1px dotted;\r\n border-color: $color-accent-1;\r\n vertical-align: middle;\r\n }\r\n .icon {\r\n display: none;\r\n }\r\n li:last-child {\r\n margin-right: 0;\r\n border-right: 0;\r\n\r\n a {\r\n margin-right: 0;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n@if $logo-grayout {\r\n #header:hover {\r\n #logo {\r\n filter: none;\r\n -webkit-filter: none;\r\n }\r\n }\r\n}\r\n@media screen and (max-width: 480px) {\r\n #header #title {\r\n display: table;\r\n margin-right: 5rem;\r\n min-height: $logo-height;\r\n h1 {\r\n display: table-cell;\r\n vertical-align: middle;\r\n }\r\n }\r\n #header #nav {\r\n ul {\r\n a:hover {\r\n background: none;\r\n }\r\n li {\r\n display: none;\r\n border-right: 0;\r\n }\r\n li.icon {\r\n position: absolute;\r\n top: 77px;\r\n right: 1rem;\r\n display: inline-block;\r\n }\r\n }\r\n ul.responsive {\r\n li {\r\n display: block;\r\n }\r\n }\r\n li:not(:first-child) {\r\n padding-top: 1rem;\r\n padding-left: $logo-width + 20px;\r\n font-size: 1rem;\r\n }\r\n }\r\n};", + "#header-post {\r\n position: fixed;\r\n top: 2rem;\r\n right: 0;\r\n display: inline-block;\r\n float: right;\r\n z-index: 100;\r\n\r\n a {\r\n background: none;\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n a.icon {\r\n background: none;\r\n\r\n &:hover {\r\n color: $color-link;\r\n }\r\n }\r\n nav {\r\n ul {\r\n display: block;\r\n\r\n list-style-image: none;\r\n\r\n list-style-position: outside;\r\n\r\n list-style-type: none;\r\n\r\n padding-inline-start: 40px;\r\n\r\n li {\r\n display: list-item;\r\n\r\n margin-right: 0px;\r\n }\r\n }\r\n }\r\n nav > ul {\r\n margin-block-end: 1em;\r\n\r\n margin-block-start: 1em;\r\n }\r\n\r\n ul {\r\n display: inline-block;\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n\r\n li {\r\n display: inline-block;\r\n margin-right: 15px;\r\n vertical-align: middle;\r\n }\r\n li:last-child {\r\n margin-right: 0;\r\n }\r\n }\r\n #menu-icon {\r\n float: right;\r\n margin-right: 2rem;\r\n margin-left: 15px;\r\n\r\n &:hover {\r\n color: $color-accent-1;\r\n }\r\n }\r\n #menu-icon-tablet {\r\n float: right;\r\n margin-right: 2rem;\r\n margin-left: 15px;\r\n\r\n &:hover {\r\n color: $color-accent-1;\r\n }\r\n }\r\n #top-icon-tablet {\r\n position: fixed;\r\n right: 2rem;\r\n bottom: 2rem;\r\n margin-right: 2rem;\r\n margin-left: 15px;\r\n\r\n &:hover {\r\n color: $color-accent-1;\r\n }\r\n }\r\n .active {\r\n color: $color-accent-1;\r\n }\r\n #menu {\r\n visibility: hidden;\r\n margin-right: 2rem;\r\n }\r\n #nav {\r\n color: $color-accent-1;\r\n letter-spacing: .01em;\r\n font-weight: 200;\r\n font-style: normal;\r\n font-size: .8rem;\r\n\r\n ul {\r\n line-height: 15px;\r\n\r\n a {\r\n margin-right: 15px;\r\n color: $color-accent-1;\r\n }\r\n a:hover {\r\n @include underline(5px, $color-accent-1);\r\n }\r\n li {\r\n border-right: 1px dotted $color-accent-1;\r\n }\r\n li:last-child {\r\n margin-right: 0;\r\n border-right: 0;\r\n\r\n a {\r\n margin-right: 0;\r\n }\r\n }\r\n }\r\n }\r\n #actions {\r\n float: right;\r\n margin-top: 2rem;\r\n margin-right: 2rem;\r\n width: 100%;\r\n text-align: right;\r\n\r\n ul {\r\n display: block;\r\n }\r\n .info {\r\n display: block;\r\n font-style: italic;\r\n }\r\n }\r\n #share {\r\n clear: both;\r\n padding-top: 1rem;\r\n padding-right: 2rem;\r\n text-align: right;\r\n\r\n li {\r\n display: block;\r\n margin: 0;\r\n }\r\n }\r\n #toc {\r\n float: right;\r\n clear: both;\r\n overflow: auto;\r\n margin-top: 1rem;\r\n padding-right: 2rem;\r\n max-width: 20em;\r\n max-height: calc(95vh - 7rem);\r\n text-align: right;\r\n\r\n a:hover {\r\n color: $color-link;\r\n }\r\n // .toc-level-1 > .toc-link\r\n // display: none\r\n\r\n nav > ul > li {\r\n color: $color-text;\r\n font-size: .8rem;\r\n\r\n &:before {\r\n color: $color-accent-1;\r\n content: \"#\";\r\n margin-right: 8px;\r\n }\r\n }\r\n nav > ul > li > ul > li {\r\n color: $color-meta;\r\n font-size: .7rem;\r\n\r\n &:before {\r\n color: $color-accent-1;\r\n content: \"·\";\r\n font-weight: bold;\r\n margin-right: 3px;\r\n }\r\n }\r\n nav > ul > li > ul > li > ul > li {\r\n color: darken($color-meta, 20%);\r\n font-size: .4rem;\r\n }\r\n .toc-level-5 {\r\n display: none;\r\n }\r\n .toc-level-6 {\r\n display: none;\r\n }\r\n .toc-number {\r\n display: none;\r\n }\r\n// smartphone + phapblet\r\n }\r\n}\r\n@media screen and (max-width: 500px) {\r\n #header-post {\r\n display: none;\r\n }\r\n}\r\n\r\n@media screen and (max-width: 900px) {\r\n #header-post {\r\n #menu-icon {\r\n display: none;\r\n }\r\n #actions {\r\n display: none;\r\n }\r\n }\r\n}\r\n@media screen and (max-width: 1199px) {\r\n #header-post {\r\n #toc {\r\n display: none;\r\n }\r\n }\r\n}\r\n@media screen and (min-width: 900px) {\r\n #header-post {\r\n #menu-icon-tablet {\r\n display: none !important;\r\n }\r\n #top-icon-tablet {\r\n display: none !important;\r\n }\r\n }\r\n}\r\n@media screen and (min-width: 1199px) {\r\n #header-post {\r\n #actions {\r\n width: auto;\r\n\r\n ul {\r\n display: inline-block;\r\n float: right;\r\n }\r\n .info {\r\n display: inline;\r\n float: left;\r\n margin-right: 2rem;\r\n font-style: italic;\r\n }\r\n }\r\n }\r\n};", + "#footer-post {\r\n position: fixed;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n z-index: 5000000;\r\n width: 100%;\r\n border-top: 1px solid $color-border;\r\n background: $color-footer-mobile-1;\r\n transition: opacity .2s;\r\n\r\n a {\r\n background: none;\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n a.icon {\r\n background: none;\r\n\r\n &:hover {\r\n color: $color-link;\r\n }\r\n }\r\n #nav-footer {\r\n padding-right: 1rem;\r\n padding-left: 1rem;\r\n background: $color-footer-mobile-2;\r\n text-align: center;\r\n\r\n a {\r\n color: $color-accent-1;\r\n font-size: 1em;\r\n }\r\n a:hover {\r\n @include underline(5px, $color-accent-1);\r\n }\r\n ul {\r\n display: table;\r\n margin: 0;\r\n padding: 0;\r\n width: 100%;\r\n list-style-type: none;\r\n\r\n li {\r\n display: inline-table;\r\n padding: 10px;\r\n width: 20%;\r\n vertical-align: middle;\r\n }\r\n }\r\n }\r\n #actions-footer {\r\n overflow: auto;\r\n margin-top: 1rem;\r\n margin-bottom: 1rem;\r\n padding-right: 1rem;\r\n padding-left: 1rem;\r\n width: 100%;\r\n text-align: center;\r\n white-space: nowrap;\r\n\r\n a {\r\n display: inline-block;\r\n padding-left: 1rem;\r\n color: $color-accent-1;\r\n }\r\n }\r\n #share-footer {\r\n padding-right: 1rem;\r\n padding-left: 1rem;\r\n background: $color-footer-mobile-2;\r\n text-align: center;\r\n\r\n ul {\r\n display: table;\r\n margin: 0;\r\n padding: 0;\r\n width: 100%;\r\n list-style-type: none;\r\n\r\n li {\r\n display: inline-table;\r\n padding: 10px;\r\n width: 20%;\r\n vertical-align: middle;\r\n }\r\n }\r\n }\r\n #toc-footer {\r\n clear: both;\r\n padding-top: 1rem;\r\n padding-bottom: 1rem;\r\n background: $color-footer-mobile-2;\r\n text-align: left;\r\n\r\n #TableOfContents {\r\n ul {\r\n margin: 0;\r\n padding-left: 20px;\r\n list-style-type: none;\r\n\r\n li {\r\n line-height: 30px;\r\n }\r\n }\r\n }\r\n a:hover {\r\n color: $color-link;\r\n }\r\n // .toc-level-1 > .toc-link\r\n // display: none\r\n\r\n #TableOfContents > ul > li {\r\n color: $color-text;\r\n font-size: .8rem;\r\n\r\n &:before {\r\n color: $color-accent-1;\r\n content: \"#\";\r\n margin-right: 8px;\r\n }\r\n }\r\n #TableOfContents > ul > li > ul > li {\r\n color: $color-meta;\r\n font-size: .7rem;\r\n line-height: 15px;\r\n\r\n &:before {\r\n color: $color-accent-1;\r\n content: \"·\";\r\n\r\n font-weight: bold;\r\n\r\n margin-right: 3px;\r\n }\r\n }\r\n #TableOfContents > ul > li > ul > li > ul > li {\r\n display: none;\r\n }\r\n // .toc-level-5\r\n // display: none\r\n\r\n // .toc-level-6\r\n // display: none\r\n\r\n // .toc-number\r\n // display: none\r\n }\r\n}\r\n@media screen and (min-width: 500px) {\r\n #footer-post-container {\r\n display: none;\r\n }\r\n};", + ".post-list {\r\n padding: 0;\r\n\r\n .post-item {\r\n margin-bottom: 1rem;\r\n margin-left: 0;\r\n list-style-type: none;\r\n\r\n .meta {\r\n display: block;\r\n margin-right: 16px;\r\n min-width: 100px;\r\n color: $color-meta;\r\n font-size: 14px;\r\n }\r\n }\r\n}\r\n@media (min-width: 480px) {\r\n .post-list {\r\n .post-item {\r\n display: flex;\r\n margin-bottom: 5px;\r\n\r\n .meta {\r\n text-align: left;\r\n }\r\n }\r\n }\r\n}\r\n.project-list {\r\n padding: 0;\r\n list-style: none;\r\n\r\n .project-item {\r\n margin-bottom: 5px;\r\n p {\r\n display: inline;\r\n }\r\n }\r\n}", + "article {\r\n header {\r\n .posttitle {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n text-transform: none;\r\n font-size: 1.5em;\r\n line-height: 1.25;\r\n }\r\n .meta {\r\n margin-top: 0;\r\n margin-bottom: 1rem;\r\n }\r\n .meta * {\r\n color: $color-accent-3;\r\n font-size: .85rem;\r\n }\r\n .author {\r\n text-transform: uppercase;\r\n letter-spacing: .01em;\r\n font-weight: 700;\r\n }\r\n .postdate {\r\n display: inline;\r\n }\r\n }\r\n .content {\r\n h2 {\r\n &:before {\r\n position: absolute;\r\n top: -4px;\r\n left: -1rem;\r\n color: $color-accent-1;\r\n content: \"#\";\r\n font-weight: bold;\r\n font-size: 1.2rem;\r\n }\r\n }\r\n }\r\n .content img,\r\n .content video {\r\n display: block;\r\n margin: auto;\r\n max-width: 100%;\r\n height: auto;\r\n\r\n /* http://webdesignerwall.com/tutorials/css-elastic-videos */\r\n .video-container {\r\n position: relative;\r\n overflow: hidden;\r\n padding-top: 56.25% e;\r\n // (9/16 * 100)% // 16:9 ratio\r\n height: 0;\r\n\r\n iframe,\r\n object,\r\n embed {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n margin-top: 0;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n }\r\n blockquote {\r\n margin: 1rem 10px;\r\n padding: .5em 10px;\r\n background: inherit;\r\n color: $color-quote;\r\n quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\r\n font-weight: bold;\r\n\r\n p {\r\n margin: 0;\r\n }\r\n &:before {\r\n margin-right: .25em;\r\n color: $color-quote;\r\n content: \"\\201C\";\r\n vertical-align: -.4em;\r\n font-size: 2em;\r\n line-height: .1em;\r\n }\r\n footer {\r\n margin: line-height 0;\r\n color: $color-meta;\r\n font-size: 11px;\r\n\r\n a {\r\n background-image: linear-gradient(transparent, transparent 5px, $color-meta 5px, $color-meta);\r\n color: $color-meta;\r\n }\r\n a:hover {\r\n background-image: linear-gradient(transparent, transparent 4px, lighten($color-meta, 20%) 4px, lighten($color-meta, 20%));\r\n color: lighten($color-meta, 20%);\r\n }\r\n cite {\r\n &:before {\r\n padding: 0 .5em;\r\n content: \"—\";\r\n }\r\n }\r\n }\r\n }\r\n .pullquote {\r\n margin: 0;\r\n width: 45%;\r\n text-align: left;\r\n\r\n &.left {\r\n margin-right: 1em;\r\n margin-left: .5em;\r\n }\r\n &.right {\r\n margin-right: .5em;\r\n margin-left: 1em;\r\n }\r\n }\r\n .caption {\r\n position: relative;\r\n display: block;\r\n margin-top: .5em;\r\n color: $color-meta;\r\n text-align: center;\r\n font-size: .9em;\r\n }\r\n }\r\n}\r\n.posttitle {\r\n text-transform: none;\r\n font-size: 1.5em;\r\n line-height: 1.25;\r\n}\r\n.article-tag {\r\n .tag-link {\r\n &:before {\r\n content: \"#\";\r\n @include underline(10px, $color-link);\r\n }\r\n }\r\n}\r\n.article-category {\r\n .category-link {\r\n @include underline(10px, $color-link);\r\n }\r\n}\r\n@media (min-width: 480px) {\r\n .article-read-time,\r\n .article-tag,\r\n .article-category {\r\n display: inline;\r\n\r\n &:before {\r\n content: \"|\";\r\n }\r\n }\r\n};", + "#archive {\r\n .post-list {\r\n padding: 0;\r\n\r\n .post-item {\r\n margin-bottom: 1rem;\r\n margin-left: 0;\r\n list-style-type: none;\r\n\r\n .meta {\r\n display: block;\r\n margin-right: 16px;\r\n min-width: 100px;\r\n color: $color-meta;\r\n font-size: 14px;\r\n }\r\n }\r\n }\r\n @media (min-width: 480px) {\r\n .post-list {\r\n .post-item {\r\n display: flex;\r\n margin-bottom: 5px;\r\n margin-left: 1rem;\r\n\r\n .meta {\r\n text-align: left;\r\n }\r\n }\r\n }\r\n }\r\n}", + ".blog-post-comments {\r\n margin-top: 4rem;\r\n}", + "#footer {\r\n position: absolute;\r\n bottom: 0;\r\n margin-bottom: 10px;\r\n width: 100%;\r\n color: $color-meta;\r\n vertical-align: top;\r\n text-align: center;\r\n font-size: 11px;\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style: none;\r\n }\r\n li {\r\n display: inline-block;\r\n margin-right: 15px;\r\n border-right: 1px solid;\r\n border-color: $color-border;\r\n vertical-align: middle;\r\n\r\n a {\r\n margin-right: 15px;\r\n }\r\n }\r\n li:last-child {\r\n margin-right: 0;\r\n border-right: 0;\r\n\r\n a {\r\n margin-right: 0;\r\n }\r\n }\r\n a {\r\n color: $color-meta;\r\n text-decoration: underline;\r\n background-image: none;\r\n }\r\n a:hover {\r\n color: lighten($color-meta, 20%);\r\n }\r\n .footer-left {\r\n height: 20px;\r\n vertical-align: middle;\r\n line-height: 20px;\r\n }\r\n}\r\n@media (min-width: 39rem) {\r\n #footer {\r\n display: flex;\r\n flex-flow: row wrap;\r\n justify-content: space-between;\r\n align-items: center;\r\n align-content: center;\r\n margin-bottom: 20px;\r\n\r\n .footer-left {\r\n align-self: flex-start;\r\n margin-right: 20px;\r\n }\r\n .footer-right {\r\n align-self: flex-end;\r\n }\r\n }\r\n};", + ".pagination {\r\n display: inline-block;\r\n margin-top: 2rem;\r\n width: 100%;\r\n text-align: center;\r\n\r\n .page-number {\r\n color: $color-text;\r\n font-size: .8rem;\r\n }\r\n a {\r\n padding: 4px 6px;\r\n border-radius: 5px;\r\n // background-color: $color-accent-1\r\n background-image: none;\r\n color: $color-text;\r\n text-decoration: none;\r\n }\r\n a:hover {\r\n background-image: none;\r\n }\r\n a:hover:not(.active) {\r\n color: $color-accent-2;\r\n }\r\n}", + ".search-input {\r\n padding: 4px 7px;\r\n width: 100%;\r\n outline: none;\r\n border: solid 1px $color-accent-3;\r\n border-radius: 5px;\r\n background-color: $color-background;\r\n color: $color-text;\r\n font-size: 1.2rem;\r\n -webkit-border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n\r\n &:focus {\r\n border: solid 1px $color-accent-1;\r\n }\r\n}\r\n#search-result {\r\n ul.search-result-list {\r\n padding: 0;\r\n list-style-type: none;\r\n }\r\n li {\r\n margin: 2em auto;\r\n }\r\n a.search-result-title {\r\n background-image: none;\r\n color: $color-text;\r\n text-transform: capitalize;\r\n font-weight: bold;\r\n line-height: 1.2;\r\n }\r\n p.search-result {\r\n overflow: hidden;\r\n margin: .4em auto;\r\n max-height: 13em;\r\n text-align: justify;\r\n font-size: .8em;\r\n }\r\n em.search-keyword {\r\n border-bottom: 1px dashed $color-link;\r\n color: $color-link;\r\n font-weight: bold;\r\n }\r\n}\r\n.search-no-result {\r\n display: none;\r\n padding-bottom: .5em;\r\n color: $color-text;\r\n}", + "#tag-cloud {\r\n .tag-cloud-title {\r\n color: $color-meta;\r\n }\r\n .tag-cloud-tags {\r\n clear: both;\r\n text-align: center;\r\n a {\r\n display: inline-block;\r\n margin: 10px;\r\n }\r\n }\r\n}", + "// ref: https://github.com/primer/primer/blob/master/modules/primer-tooltips/lib/tooltips.scss\r\n.tooltipped {\r\n position: relative;\r\n} \r\n// This is the tooltip bubble\r\n.tooltipped::after {\r\n position: absolute;\r\n z-index: 1000000;\r\n display: none;\r\n padding: .2em .5em;\r\n -webkit-font-smoothing: subpixel-antialiased;\r\n color: $color-background;\r\n font-display: swap;\r\n font-weight: 400;\r\n font-size: $font-size * 0.8;\r\n font-family: $font-family-body;\r\n line-height: $line-height;\r\n text-rendering: geometricPrecision;\r\n text-align: center;\r\n word-wrap: break-word;\r\n white-space: pre;\r\n content: attr(aria-label);\r\n background: $color-text;\r\n border-radius: 3px;\r\n opacity: 0;\r\n} \r\n// This is the tooltip arrow\r\n.tooltipped::before {\r\n position: absolute;\r\n z-index: 1000001;\r\n display: none;\r\n width: 0;\r\n height: 0;\r\n color: $color-text;\r\n pointer-events: none;\r\n content: '';\r\n border: 6px solid transparent;\r\n opacity: 0;\r\n} \r\n// delay animation for tooltip\r\n@keyframes tooltip-appear {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n};\r\n \r\n// This will indicate when we'll activate the tooltip\r\n.tooltipped:hover,\r\n.tooltipped:active,\r\n.tooltipped:focus {\r\n &::before,\r\n &::after {\r\n display: inline-block;\r\n text-decoration: none;\r\n animation-name: tooltip-appear;\r\n animation-duration: 0.1s;\r\n animation-fill-mode: forwards;\r\n animation-timing-function: ease-in;\r\n } \r\n// Tooltipped south\r\n}\r\n.tooltipped-s,\r\n.tooltipped-sw {\r\n &::after {\r\n top: 100%;\r\n right: 50%;\r\n margin-top: 6px;\r\n }\r\n &::before {\r\n top: auto;\r\n right: 50%;\r\n bottom: -7px;\r\n margin-right: -6px;\r\n border-bottom-color: $color-text;\r\n }\r\n}\r\n.tooltipped-sw::after {\r\n margin-right: -16px;\r\n} \r\n// Move the tooltip body to the center of the object.\r\n.tooltipped-s::after {\r\n transform: translateX(50%);\r\n}", + "#categories {\r\n .category-list-title {\r\n color: $color-meta;\r\n }\r\n .category-list {\r\n .category-list-item {\r\n .category-list-count {\r\n color: $color-meta;\r\n }\r\n .category-list-count:before {\r\n content: \" (\";\r\n }\r\n .category-list-count:after {\r\n content: \")\";\r\n }\r\n }\r\n }\r\n}" + ], + "names": [], + "mappings": "AGCA,AAAA,OAAO,AAAC,CACN,OAAO,CAAE,MAAM,CAChB,AACD,AAAA,MAAM,AAAC,CACL,OAAO,CAAE,KAAK,CACf,AACD,AAAA,aAAa,AAAC,CACZ,OAAO,CAAE,YAAY,CACtB,AACD,AAAA,MAAM,AAAC,CACL,OAAO,CAAE,KAAK,CACf,AACD,AAAA,WAAW,AAAC,CACV,OAAO,CAAE,UAAU,CACpB,AACD,AAAA,gBAAgB,AAAC,CACf,QAAQ,CAAE,MAAM,CACjB,AACD,AAAA,gBAAgB,AAAC,CACf,QAAQ,CAAE,MAAM,CACjB,AACD,AAAA,cAAc,AAAC,CACb,QAAQ,CAAE,IAAI,CACf,AACD,AAAA,SAAS,CAAC,MAAM,CAChB,SAAS,CAAC,KAAK,AAAC,CACd,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,GAAG,CACb,AACD,AAAA,SAAS,CAAC,KAAK,AAAC,CACd,KAAK,CAAE,IAAI,CACZ,AACD,AAAA,KAAK,AAAC,CACJ,KAAK,CAAE,IAAI,CACZ,AACD,AAAA,MAAM,AAAC,CACL,KAAK,CAAE,KAAK,CACb,AACD,AAAA,IAAI,AAAC,CACH,SAAS,CAAE,IAAI,CAChB,AACD,AAAA,SAAS,AAAC,CACR,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAChB,aAAa,CAAE,QAAQ,CACvB,WAAW,CAAE,MAAM,CACpB,AACD,AAAA,YAAY,AAAC,CACX,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,YAAY,AAAC,CACX,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,YAAY,AAAC,CACX,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,YAAY,AAAC,CACX,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,WAAW,AAAC,CACV,UAAU,CAAE,UAAU,CACvB,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,CAAC,CACV,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,CAAC,CACd,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,CAAC,CAChB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,CAAC,CACjB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,CAAC,CACf,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,CAAC,CACf,WAAW,CAAE,CAAC,CACf,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,CAAC,CACb,aAAa,CAAE,CAAC,CACjB,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,KAAK,CACd,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,KAAK,CAClB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,KAAK,CACpB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,KAAK,CACrB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,KAAK,CACnB,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,KAAK,CACjB,aAAa,CAAE,KAAK,CACrB,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,IAAI,CACb,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CACjB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,IAAI,CACb,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CACjB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,IAAI,CACb,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CACjB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,KAAK,AAAC,CACJ,YAAY,CAAE,MAAM,CACpB,WAAW,CAAE,MAAM,CACpB,AACD,AAAA,KAAK,AAAC,CACJ,YAAY,CAAE,KAAK,CACnB,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,KAAK,AAAC,CACJ,YAAY,CAAE,KAAK,CACnB,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,KAAK,AAAC,CACJ,YAAY,CAAE,KAAK,CACnB,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,QAAQ,AAAC,CACP,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,QAAQ,AAAC,CACP,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,QAAQ,AAAC,CACP,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,GAAG,AAAC,CACF,OAAO,CAAE,CAAC,CACX,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,CAAC,CACf,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,CAAC,CACjB,AACD,AAAA,IAAI,AAAC,CACH,cAAc,CAAE,CAAC,CAClB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,CAAC,CAChB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,CAAC,CAChB,YAAY,CAAE,CAAC,CAChB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,CAAC,CACd,cAAc,CAAE,CAAC,CAClB,AACD,AAAA,GAAG,AAAC,CACF,OAAO,CAAE,KAAK,CACf,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,KAAK,CACnB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,KAAK,CACrB,AACD,AAAA,IAAI,AAAC,CACH,cAAc,CAAE,KAAK,CACtB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,KAAK,CACpB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,KAAK,CAClB,cAAc,CAAE,KAAK,CACtB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,KAAK,CACpB,YAAY,CAAE,KAAK,CACpB,AACD,AAAA,GAAG,AAAC,CACF,OAAO,CAAE,IAAI,CACd,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CACjB,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,GAAG,AAAC,CACF,OAAO,CAAE,IAAI,CACd,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CACjB,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,GAAG,AAAC,CACF,OAAO,CAAE,IAAI,CACd,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,IAAI,AAAC,CACH,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,IAAI,CACjB,cAAc,CAAE,IAAI,CACrB,AACD,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CACnB,AE7TD,AAAA,EAAE,CACF,GAAG,AAAC,CACF,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACnB,KAAK,CHMU,OAAO,CGLtB,cAAc,CAAE,KAAK,CACrB,WAAW,CAAE,GAAG,CAChB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,KAAK,CDThB,uBAAuB,CAAE,SAAS,CAClC,sBAAsB,CAAE,WAAW,CCWpC,AACD,AAAA,EAAE,CACF,GAAG,AAAC,CACF,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,KAAK,CACpB,KAAK,CHTU,OAAO,CGUtB,cAAc,CAAE,IAAI,CACpB,cAAc,CAAE,MAAM,CACtB,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,IAAI,CAChB,AACD,AAAA,EAAE,AAAC,CACD,KAAK,CHhBU,OAAO,CGiBtB,eAAe,CAAE,SAAS,CAC1B,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,EAAE,CACF,EAAE,CACF,EAAE,AAAC,CACD,OAAO,CAAE,MAAM,CACf,eAAe,CAAE,IAAI,CACrB,KAAK,CH3BU,OAAO,CG4BtB,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,EAAE,CACF,EAAE,CACF,EAAE,CACF,EAAE,AAAC,CACD,UAAU,CAAE,KAAK,CACjB,aAAa,CAAE,KAAK,CACrB,AACD,AAAA,EAAE,AAAC,CACD,MAAM,CAAE,KAAI,CAAC,MAAM,CHvCJ,OAAO,CGwCtB,OAAO,CAAE,EAAE,CACX,MAAM,CAAE,CAAC,CACT,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACpB,AACD,AAAA,MAAM,AAAC,CACL,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,EAAE,CACF,IAAI,AAAC,CACH,UAAU,CAAE,MAAM,CACnB,AACD,AAAA,GAAG,CACH,GAAG,AAAC,CACF,QAAQ,CAAE,QAAQ,CAClB,cAAc,CAAE,QAAQ,CACxB,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,CAAC,CACf,AACD,AAAA,GAAG,AAAC,CACF,GAAG,CAAE,KAAK,CACX,AACD,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,KAAK,CACd,AACD,AAAA,KAAK,AAAC,CACJ,SAAS,CAAE,KAAK,CACjB,AACD,AAAA,OAAO,CACP,IAAI,AAAC,CACH,aAAa,CAAE,UAAU,CAC1B,AACD,AAAA,EAAE,CACF,EAAE,CACF,EAAE,AAAC,CACD,WAAW,CJhFC,KAAK,CIiFlB,AACD,AAAA,EAAE,CAAC,EAAE,CACL,EAAE,CAAC,EAAE,CACL,EAAE,CAAC,EAAE,CACL,EAAE,CAAC,EAAE,AAAC,CACJ,UAAU,CAAE,CAAC,CACb,aAAa,CAAE,CAAC,CACjB,AACD,AAAA,EAAE,AAAC,CACD,UAAU,CAAE,OAAO,CACpB,AACD,AAAA,EAAE,AAAC,CACD,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,KAAK,AAAC,CACJ,KAAK,CAAE,IAAI,CACX,eAAe,CAAE,QAAQ,CACzB,UAAU,CAAE,IAAI,CAChB,SAAS,CAAE,IAAgB,CAC3B,QAAQ,CAAE,IAAI,CACd,OAAO,CAAE,KAAK,CACf,AACD,AAAA,EAAE,AAAC,CACD,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,GAAG,CAAC,MAAM,CHzGZ,IAAI,CG0GjB,KAAK,CHpGU,OAAO,CGqGtB,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,IAAgB,CAC5B,AACD,AAAA,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACd,aAAa,CAAE,IAAI,CACpB,ACtHD,UAAU,CACR,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,gBAAgB,CAC7B,YAAY,CAAE,IAAI,CAClB,GAAG,CAAE,uBAAuB,CAAE,uBAAuB,CAAE,iEAAiE,CAAC,eAAe,CAAE,+DAA+D,CAAC,cAAc,CAAE,6DAA6D,CAAC,2BAA2B,CAAE,yDAAyD,CAAC,kBAAkB,CNKnY,AAAA,CAAC,CACD,CAAC,CAAC,MAAM,CACR,CAAC,CAAC,KAAK,AAAC,CACN,UAAU,CAAE,UAAU,CACvB,AACD,AAAA,IAAI,AAAC,CACH,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,GAAG,CAAC,KAAK,CETV,OAAO,CFUlB,wBAAwB,CAAE,IAAI,CAC9B,oBAAoB,CAAE,IAAI,CAC3B,AACD,AAAA,IAAI,AAAC,CACH,MAAM,CAAE,CAAC,CACT,MAAM,CAAE,IAAI,CACZ,gBAAgB,CExBC,IAAO,CFyBxB,KAAK,CEjBM,OAAO,CFkBlB,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,GAAG,CAChB,SAAS,CCzBC,IAAI,CD0Bd,WAAW,CC7BM,gBAAgB,CAAE,SAAS,CD8B5C,WAAW,CC1BC,KAAK,CD2BjB,cAAc,CAAE,kBAAkB,CAClC,IAAI,CAAE,CAAC,CIhCP,uBAAuB,CAAE,SAAS,CAClC,sBAAsB,CAAE,WAAW,CJoCpC,AACD,AAAA,QAAQ,AAAC,CACP,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,MAAM,CACtB,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,UAAU,CAyD1B,AA9DD,AAOE,QAPM,CAON,CAAC,AAAC,CIzCF,OAAO,CJ0CY,IAAI,CIzCvB,YAAY,CJyCO,IAAI,CIxCvB,WAAW,CJwCQ,IAAI,CIvCvB,eAAe,CJuCI,IAAI,CACtB,AATH,AAUE,QAVM,CAUN,IAAI,AAAC,CI5CL,OAAO,CJ6CY,MAAM,CI5CzB,YAAY,CJ4CO,MAAM,CI3CzB,WAAW,CJ2CQ,MAAM,CI1CzB,eAAe,CJ0CI,MAAM,CACxB,AAZH,AAaE,QAbM,CAaN,CAAC,AAAC,CACA,KAAK,CE5CI,OAAO,CF6ChB,eAAe,CAAE,IAAI,CI3CvB,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CJ+C1B,AAtBH,AAmBI,QAnBI,CAaN,CAAC,CAMG,KAAK,AAAC,CACN,gBAAgB,CAAE,mEAA2E,CAC9F,AArBL,AAuBE,QAvBM,CAuBN,CAAC,AAAA,KAAK,AAAC,CACL,UAAU,CAAE,IAAI,CAKjB,AA7BH,AA0BI,QA1BI,CAuBN,CAAC,AAAA,KAAK,CAGF,KAAK,AAAC,CACN,KAAK,CE1DE,OAAsB,CF2D9B,AA5BL,AA8BE,QA9BM,CA8BN,EAAE,CAAC,CAAC,CA9BN,QAAQ,CA+BN,GAAG,CAAC,CAAC,CA/BP,QAAQ,CAgCN,EAAE,CAAC,CAAC,CAhCN,QAAQ,CAiCN,EAAE,CAAC,CAAC,CAjCN,QAAQ,CAkCN,EAAE,CAAC,CAAC,CAlCN,QAAQ,CAmCN,EAAE,CAAC,CAAC,CAnCN,QAAQ,CAoCN,EAAE,CAAC,CAAC,AAAC,CACH,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,IAAI,CACtB,AAxCH,AAyCE,QAzCM,CAyCN,EAAE,CAAC,CAAC,CAAC,KAAK,CAzCZ,QAAQ,CA0CN,GAAG,CAAC,CAAC,CAAC,KAAK,CA1Cb,QAAQ,CA2CN,EAAE,CAAC,CAAC,CAAC,KAAK,CA3CZ,QAAQ,CA4CN,EAAE,CAAC,CAAC,CAAC,KAAK,CA5CZ,QAAQ,CA6CN,EAAE,CAAC,CAAC,CAAC,KAAK,CA7CZ,QAAQ,CA8CN,EAAE,CAAC,CAAC,CAAC,KAAK,CA9CZ,QAAQ,CA+CN,EAAE,CAAC,CAAC,CAAC,KAAK,AAAC,CI3EX,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CJ0E1B,AAjDH,AAmDI,QAnDI,CAkDN,EAAE,CACA,CAAC,AAAC,CACA,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,IAAI,CACtB,AAvDL,AA0DI,QA1DI,CAyDN,EAAE,CACA,CAAC,CAAC,KAAK,AAAC,CItFV,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CJqFxB,AAGL,MAAM,mBACJ,CAAA,AAAA,WAAW,AAAC,CACV,cAAc,CAAE,GAAG,CACnB,aAAa,CAAE,IAAI,CASpB,AAXD,AAIE,WAJS,CAIT,YAAY,AAAC,CACX,IAAI,CAAE,OAAO,CACb,YAAY,CAAE,IAAI,CACnB,AAPH,AAQE,WARS,CAQT,CAAC,AAAC,CACA,IAAI,CAAE,OAAO,CACd,CACF,AAEH,AAAA,UAAU,AAAC,CACT,SAAS,CC/GE,KAAK,CDgHjB,AACD,MAAM,mBACJ,CAAA,AAAA,IAAI,AAAC,CACH,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CACnB,AACD,AAAA,IAAI,AAAC,CACH,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACpB,CAJA,AAOH,MAAM,mBACJ,CAAA,AAAA,CAAC,AAAC,CACA,UAAU,CAAE,OAAO,CACpB,CAAA,AOrIH,AAAA,OAAO,AAAC,CACN,MAAM,CAAE,WAAW,CACnB,KAAK,CAAE,IAAI,CA0EZ,AA5ED,AAIE,OAJK,CAIL,EAAE,CAJJ,OAAO,CAKL,GAAG,AAAC,CACF,UAAU,CAAE,CAAC,CACb,aAAa,CAAE,CAAC,CAChB,KAAK,CLCI,OAAO,CKAhB,cAAc,CAAE,KAAK,CACrB,WAAW,CAAE,GAAG,CAChB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,MAAM,CACjB,WAAW,CAAE,IAAI,CHZnB,uBAAuB,CAAE,SAAS,CAClC,sBAAsB,CAAE,WAAW,CGclC,AAhBH,AAiBE,OAjBK,CAiBL,CAAC,AAAC,CACA,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,IAAI,CACtB,AArBH,AAsBE,OAtBK,CAsBL,KAAK,AAAC,CACJ,OAAO,CAAE,YAAY,CACrB,KAAK,CAAE,IAAI,CACX,YAAY,CAAE,IAAI,CAClB,KAAK,CNlBI,IAAI,CMmBb,MAAM,CNlBI,IAAI,CMmBd,aAAa,CAAE,GAAG,CAClB,eAAe,CNrBN,IAAI,CACH,IAAI,CMqBd,iBAAiB,CAAE,SAAS,CAE1B,MAAM,CAAE,eAAe,CACvB,cAAc,CAAE,eAAe,CAElC,AAnCH,AAoCE,OApCK,CAoCL,IAAI,AAAC,CACH,KAAK,CLzBQ,OAAO,CK0BpB,cAAc,CAAE,KAAK,CACrB,WAAW,CAAE,GAAG,CAChB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,KAAK,CAkCjB,AA3EH,AA2CI,OA3CG,CAoCL,IAAI,CAOF,EAAE,AAAC,CACD,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,eAAe,CAAE,IAAI,CACrB,WAAW,CAAE,IAAI,CA2BlB,AA1EL,AAiDM,OAjDC,CAoCL,IAAI,CAOF,EAAE,CAMA,CAAC,AAAC,CACA,YAAY,CAAE,IAAI,CAClB,KAAK,CLvCI,OAAO,CKwCjB,AApDP,AAqDM,OArDC,CAoCL,IAAI,CAOF,EAAE,CAUA,CAAC,CAAC,KAAK,AAAC,CH1CZ,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CGyCtB,AAvDP,AAwDM,OAxDC,CAoCL,IAAI,CAOF,EAAE,CAaA,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,YAAY,CAAE,IAAI,CAClB,YAAY,CAAE,UAAU,CACxB,YAAY,CLhDH,OAAO,CKiDhB,cAAc,CAAE,MAAM,CACvB,AA9DP,AA+DM,OA/DC,CAoCL,IAAI,CAOF,EAAE,CAoBA,KAAK,AAAC,CACJ,OAAO,CAAE,IAAI,CACd,AAjEP,AAkEM,OAlEC,CAoCL,IAAI,CAOF,EAAE,CAuBA,EAAE,CAAC,UAAU,AAAC,CACZ,YAAY,CAAE,CAAC,CACf,YAAY,CAAE,CAAC,CAKhB,AAzEP,AAsEQ,OAtED,CAoCL,IAAI,CAOF,EAAE,CAuBA,EAAE,CAAC,UAAU,CAIX,CAAC,AAAC,CACA,YAAY,CAAE,CAAC,CAChB,AAMP,AACE,OADK,CAAC,KAAK,CACX,KAAK,AAAC,CACJ,MAAM,CAAE,IAAI,CACZ,cAAc,CAAE,IAAI,CACrB,AAGL,MAAM,8BACJ,CAAA,AAAA,OAAO,CAAC,MAAM,AAAC,CACb,OAAO,CAAE,KAAK,CACd,YAAY,CAAE,IAAI,CAClB,UAAU,CNhFA,IAAI,CMqFf,AARD,AAIE,OAJK,CAAC,MAAM,CAIZ,EAAE,AAAC,CACD,OAAO,CAAE,UAAU,CACnB,cAAc,CAAE,MAAM,CACvB,AAEH,AAEI,OAFG,CAAC,IAAI,CACV,EAAE,CACA,CAAC,CAAC,KAAK,AAAC,CACN,UAAU,CAAE,IAAI,CACjB,AAJL,AAKI,OALG,CAAC,IAAI,CACV,EAAE,CAIA,EAAE,AAAC,CACD,OAAO,CAAE,IAAI,CACb,YAAY,CAAE,CAAC,CAChB,AARL,AASI,OATG,CAAC,IAAI,CACV,EAAE,CAQA,EAAE,AAAA,KAAK,AAAC,CACN,QAAQ,CAAE,QAAQ,CAClB,GAAG,CAAE,IAAI,CACT,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,YAAY,CACtB,AAdL,AAiBI,OAjBG,CAAC,IAAI,CAgBV,EAAE,AAAA,WAAW,CACX,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACf,AAnBL,AAqBE,OArBK,CAAC,IAAI,CAqBV,EAAE,CAAA,GAAK,EAAC,WAAW,CAAE,CACnB,WAAW,CAAE,IAAI,CACjB,YAAY,CAAE,IAAkB,CAChC,SAAS,CAAE,IAAI,CAChB,CA1BF,AC9FH,AAAA,YAAY,AAAC,CACX,QAAQ,CAAE,KAAK,CACf,GAAG,CAAE,IAAI,CACT,KAAK,CAAE,CAAC,CACR,OAAO,CAAE,YAAY,CACrB,KAAK,CAAE,KAAK,CACZ,OAAO,CAAE,GAAG,CAsMb,AA5MD,AAQE,YARU,CAQV,CAAC,AAAC,CACA,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,IAAI,CACtB,AAZH,AAaE,YAbU,CAaV,CAAC,AAAA,KAAK,AAAC,CACL,UAAU,CAAE,IAAI,CAKjB,AAnBH,AAgBI,YAhBQ,CAaV,CAAC,AAAA,KAAK,CAGF,KAAK,AAAC,CACN,KAAK,CNTE,OAAsB,CMU9B,AAlBL,AAqBI,YArBQ,CAoBV,GAAG,CACD,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CAEd,gBAAgB,CAAE,IAAI,CAEtB,mBAAmB,CAAE,OAAO,CAE5B,eAAe,CAAE,IAAI,CAErB,oBAAoB,CAAE,IAAI,CAO3B,AArCL,AAgCM,YAhCM,CAoBV,GAAG,CACD,EAAE,CAWA,EAAE,AAAC,CACD,OAAO,CAAE,SAAS,CAElB,YAAY,CAAE,GAAG,CAClB,AApCP,AAuCE,YAvCU,CAuCV,GAAG,CAAG,EAAE,AAAC,CACP,gBAAgB,CAAE,GAAG,CAErB,kBAAkB,CAAE,GAAG,CACxB,AA3CH,AA6CE,YA7CU,CA6CV,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,eAAe,CAAE,IAAI,CAUtB,AA3DH,AAmDI,YAnDQ,CA6CV,EAAE,CAMA,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,YAAY,CAAE,IAAI,CAClB,cAAc,CAAE,MAAM,CACvB,AAvDL,AAwDI,YAxDQ,CA6CV,EAAE,CAWA,EAAE,CAAC,UAAU,AAAC,CACZ,YAAY,CAAE,CAAC,CAChB,AA1DL,AA4DE,YA5DU,CA4DV,UAAU,AAAC,CACT,KAAK,CAAE,KAAK,CACZ,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAKlB,AApEH,AAiEI,YAjEQ,CA4DV,UAAU,CAKN,KAAK,AAAC,CACN,KAAK,CNtDM,OAAO,CMuDnB,AAnEL,AAqEE,YArEU,CAqEV,iBAAiB,AAAC,CAChB,KAAK,CAAE,KAAK,CACZ,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAKlB,AA7EH,AA0EI,YA1EQ,CAqEV,iBAAiB,CAKb,KAAK,AAAC,CACN,KAAK,CN/DM,OAAO,CMgEnB,AA5EL,AA8EE,YA9EU,CA8EV,gBAAgB,AAAC,CACf,QAAQ,CAAE,KAAK,CACf,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,IAAI,CAKlB,AAxFH,AAqFI,YArFQ,CA8EV,gBAAgB,CAOZ,KAAK,AAAC,CACN,KAAK,CN1EM,OAAO,CM2EnB,AAvFL,AAyFE,YAzFU,CAyFV,OAAO,AAAC,CACN,KAAK,CN9EQ,OAAO,CM+ErB,AA3FH,AA4FE,YA5FU,CA4FV,KAAK,AAAC,CACJ,UAAU,CAAE,MAAM,CAClB,YAAY,CAAE,IAAI,CACnB,AA/FH,AAgGE,YAhGU,CAgGV,IAAI,AAAC,CACH,KAAK,CNrFQ,OAAO,CMsFpB,cAAc,CAAE,KAAK,CACrB,WAAW,CAAE,GAAG,CAChB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,KAAK,CAwBjB,AA7HH,AAuGI,YAvGQ,CAgGV,IAAI,CAOF,EAAE,AAAC,CACD,WAAW,CAAE,IAAI,CAoBlB,AA5HL,AA0GM,YA1GM,CAgGV,IAAI,CAOF,EAAE,CAGA,CAAC,AAAC,CACA,YAAY,CAAE,IAAI,CAClB,KAAK,CNhGI,OAAO,CMiGjB,AA7GP,AA8GM,YA9GM,CAgGV,IAAI,CAOF,EAAE,CAOA,CAAC,CAAC,KAAK,AAAC,CJnGZ,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CIkGtB,AAhHP,AAiHM,YAjHM,CAgGV,IAAI,CAOF,EAAE,CAUA,EAAE,AAAC,CACD,YAAY,CAAE,GAAG,CAAC,MAAM,CNtGf,OAAO,CMuGjB,AAnHP,AAoHM,YApHM,CAgGV,IAAI,CAOF,EAAE,CAaA,EAAE,CAAC,UAAU,AAAC,CACZ,YAAY,CAAE,CAAC,CACf,YAAY,CAAE,CAAC,CAKhB,AA3HP,AAwHQ,YAxHI,CAgGV,IAAI,CAOF,EAAE,CAaA,EAAE,CAAC,UAAU,CAIX,CAAC,AAAC,CACA,YAAY,CAAE,CAAC,CAChB,AA1HT,AA8HE,YA9HU,CA8HV,QAAQ,AAAC,CACP,KAAK,CAAE,KAAK,CACZ,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,IAAI,CAClB,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,KAAK,CASlB,AA5IH,AAqII,YArIQ,CA8HV,QAAQ,CAON,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACf,AAvIL,AAwII,YAxIQ,CA8HV,QAAQ,CAUN,KAAK,AAAC,CACJ,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,MAAM,CACnB,AA3IL,AA6IE,YA7IU,CA6IV,MAAM,AAAC,CACL,KAAK,CAAE,IAAI,CACX,WAAW,CAAE,IAAI,CACjB,aAAa,CAAE,IAAI,CACnB,UAAU,CAAE,KAAK,CAMlB,AAvJH,AAmJI,YAnJQ,CA6IV,MAAM,CAMJ,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CACV,AAtJL,AAwJE,YAxJU,CAwJV,IAAI,AAAC,CACH,KAAK,CAAE,KAAK,CACZ,KAAK,CAAE,IAAI,CACX,QAAQ,CAAE,IAAI,CACd,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACnB,SAAS,CAAE,IAAI,CACf,UAAU,CAAE,iBAAiB,CAC7B,UAAU,CAAE,KAAK,CA2ClB,AA3MH,AAkKI,YAlKQ,CAwJV,IAAI,CAUF,CAAC,CAAC,KAAK,AAAC,CACN,KAAK,CN3JE,OAAsB,CM4J9B,AApKL,AAwKI,YAxKQ,CAwJV,IAAI,CAgBF,GAAG,CAAG,EAAE,CAAG,EAAE,AAAC,CACZ,KAAK,CNhKE,OAAO,CMiKd,SAAS,CAAE,KAAK,CAOjB,AAjLL,AA4KM,YA5KM,CAwJV,IAAI,CAgBF,GAAG,CAAG,EAAE,CAAG,EAAE,CAIT,MAAM,AAAC,CACP,KAAK,CNjKI,OAAO,CMkKhB,OAAO,CAAE,GAAG,CACZ,YAAY,CAAE,GAAG,CAClB,AAhLP,AAkLI,YAlLQ,CAwJV,IAAI,CA0BF,GAAG,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,AAAC,CACtB,KAAK,CN7KE,IAAI,CM8KX,SAAS,CAAE,KAAK,CAQjB,AA5LL,AAsLM,YAtLM,CAwJV,IAAI,CA0BF,GAAG,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAInB,MAAM,AAAC,CACP,KAAK,CN3KI,OAAO,CM4KhB,OAAO,CAAE,GAAG,CACZ,WAAW,CAAE,IAAI,CACjB,YAAY,CAAE,GAAG,CAClB,AA3LP,AA6LI,YA7LQ,CAwJV,IAAI,CAqCF,GAAG,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,AAAC,CAChC,KAAK,CNxLE,IAAI,CMyLX,SAAS,CAAE,KAAK,CACjB,AAhML,AAiMI,YAjMQ,CAwJV,IAAI,CAyCF,YAAY,AAAC,CACX,OAAO,CAAE,IAAI,CACd,AAnML,AAoMI,YApMQ,CAwJV,IAAI,CA4CF,YAAY,AAAC,CACX,OAAO,CAAE,IAAI,CACd,AAtML,AAuMI,YAvMQ,CAwJV,IAAI,CA+CF,WAAW,AAAC,CACV,OAAO,CAAE,IAAI,CACd,AAIL,MAAM,8BACJ,CAAA,AAAA,YAAY,AAAC,CACX,OAAO,CAAE,IAAI,CACd,CAAA,AAGH,MAAM,8BAEF,CADF,AACE,YADU,CACV,UAAU,AAAC,CACT,OAAO,CAAE,IAAI,CACd,AAHH,AAIE,YAJU,CAIV,QAAQ,AAAC,CACP,OAAO,CAAE,IAAI,CACd,CAHA,AAML,MAAM,+BAEF,CADF,AACE,YADU,CACV,IAAI,AAAC,CACH,OAAO,CAAE,IAAI,CACd,CAAA,AAGL,MAAM,8BAEF,CADF,AACE,YADU,CACV,iBAAiB,AAAC,CAChB,OAAO,CAAE,eAAe,CACzB,AAHH,AAIE,YAJU,CAIV,gBAAgB,AAAC,CACf,OAAO,CAAE,eAAe,CACzB,CAHA,AAML,MAAM,+BAEF,CADF,AACE,YADU,CACV,QAAQ,AAAC,CACP,KAAK,CAAE,IAAI,CAYZ,AAdH,AAII,YAJQ,CACV,QAAQ,CAGN,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,KAAK,CAAE,KAAK,CACb,AAPL,AAQI,YARQ,CACV,QAAQ,CAON,KAAK,AAAC,CACJ,OAAO,CAAE,MAAM,CACf,KAAK,CAAE,IAAI,CACX,YAAY,CAAE,IAAI,CAClB,UAAU,CAAE,MAAM,CACnB,CACF,AC7PL,AAAA,YAAY,AAAC,CACX,QAAQ,CAAE,KAAK,CACf,KAAK,CAAE,CAAC,CACR,MAAM,CAAE,CAAC,CACT,IAAI,CAAE,CAAC,CACP,OAAO,CAAE,OAAO,CAChB,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,GAAG,CAAC,KAAK,CPFR,IAAI,COGjB,UAAU,CPPO,OAAO,COQxB,UAAU,CAAE,WAAW,CA2IxB,AApJD,AAWE,YAXU,CAWV,CAAC,AAAC,CACA,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,IAAI,CACtB,AAfH,AAgBE,YAhBU,CAgBV,CAAC,AAAA,KAAK,AAAC,CACL,UAAU,CAAE,IAAI,CAKjB,AAtBH,AAmBI,YAnBQ,CAgBV,CAAC,AAAA,KAAK,CAGF,KAAK,AAAC,CACN,KAAK,CPZE,OAAsB,COa9B,AArBL,AAuBE,YAvBU,CAuBV,WAAW,AAAC,CACV,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CAClB,UAAU,CPzBK,OAAO,CO0BtB,UAAU,CAAE,MAAM,CAuBnB,AAlDH,AA6BI,YA7BQ,CAuBV,WAAW,CAMT,CAAC,AAAC,CACA,KAAK,CPlBM,OAAO,COmBlB,SAAS,CAAE,GAAG,CACf,AAhCL,AAiCI,YAjCQ,CAuBV,WAAW,CAUT,CAAC,CAAC,KAAK,AAAC,CLtBV,gBAAgB,CAAE,mEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CKqBxB,AAnCL,AAoCI,YApCQ,CAuBV,WAAW,CAaT,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,KAAK,CAAE,IAAI,CACX,eAAe,CAAE,IAAI,CAQtB,AAjDL,AA2CM,YA3CM,CAuBV,WAAW,CAaT,EAAE,CAOA,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,IAAI,CACb,KAAK,CAAE,GAAG,CACV,cAAc,CAAE,MAAM,CACvB,AAhDP,AAmDE,YAnDU,CAmDV,eAAe,AAAC,CACd,QAAQ,CAAE,IAAI,CACd,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACnB,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CAClB,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,MAAM,CAOpB,AAlEH,AA6DI,YA7DQ,CAmDV,eAAe,CAUb,CAAC,AAAC,CACA,OAAO,CAAE,YAAY,CACrB,YAAY,CAAE,IAAI,CAClB,KAAK,CPpDM,OAAO,COqDnB,AAjEL,AAmEE,YAnEU,CAmEV,aAAa,AAAC,CACZ,aAAa,CAAE,IAAI,CACnB,YAAY,CAAE,IAAI,CAClB,UAAU,CPrEK,OAAO,COsEtB,UAAU,CAAE,MAAM,CAgBnB,AAvFH,AAyEI,YAzEQ,CAmEV,aAAa,CAMX,EAAE,AAAC,CACD,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,KAAK,CAAE,IAAI,CACX,eAAe,CAAE,IAAI,CAQtB,AAtFL,AAgFM,YAhFM,CAmEV,aAAa,CAMX,EAAE,CAOA,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,IAAI,CACb,KAAK,CAAE,GAAG,CACV,cAAc,CAAE,MAAM,CACvB,AArFP,AAwFE,YAxFU,CAwFV,WAAW,AAAC,CACV,KAAK,CAAE,IAAI,CACX,WAAW,CAAE,IAAI,CACjB,cAAc,CAAE,IAAI,CACpB,UAAU,CP3FK,OAAO,CO4FtB,UAAU,CAAE,IAAI,CAsDjB,AAnJH,AAgGM,YAhGM,CAwFV,WAAW,CAOT,gBAAgB,CACd,EAAE,AAAC,CACD,MAAM,CAAE,CAAC,CACT,YAAY,CAAE,IAAI,CAClB,eAAe,CAAE,IAAI,CAKtB,AAxGP,AAqGQ,YArGI,CAwFV,WAAW,CAOT,gBAAgB,CACd,EAAE,CAKA,EAAE,AAAC,CACD,WAAW,CAAE,IAAI,CAClB,AAvGT,AA0GI,YA1GQ,CAwFV,WAAW,CAkBT,CAAC,CAAC,KAAK,AAAC,CACN,KAAK,CPnGE,OAAsB,COoG9B,AA5GL,AAgHI,YAhHQ,CAwFV,WAAW,CAwBT,gBAAgB,CAAG,EAAE,CAAG,EAAE,AAAC,CACzB,KAAK,CPxGE,OAAO,COyGd,SAAS,CAAE,KAAK,CAOjB,AAzHL,AAoHM,YApHM,CAwFV,WAAW,CAwBT,gBAAgB,CAAG,EAAE,CAAG,EAAE,CAItB,MAAM,AAAC,CACP,KAAK,CPzGI,OAAO,CO0GhB,OAAO,CAAE,GAAG,CACZ,YAAY,CAAE,GAAG,CAClB,AAxHP,AA0HI,YA1HQ,CAwFV,WAAW,CAkCT,gBAAgB,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,AAAC,CACnC,KAAK,CPrHE,IAAI,COsHX,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,IAAI,CAUlB,AAvIL,AA+HM,YA/HM,CAwFV,WAAW,CAkCT,gBAAgB,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAKhC,MAAM,AAAC,CACP,KAAK,CPpHI,OAAO,COqHhB,OAAO,CAAE,GAAG,CAEZ,WAAW,CAAE,IAAI,CAEjB,YAAY,CAAE,GAAG,CAClB,AAtIP,AAwII,YAxIQ,CAwFV,WAAW,CAgDT,gBAAgB,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,AAAC,CAC7C,OAAO,CAAE,IAAI,CACd,AAWL,MAAM,8BACJ,CAAA,AAAA,sBAAsB,AAAC,CACrB,OAAO,CAAE,IAAI,CACd,CAAA,ACxJH,AAAA,UAAU,AAAC,CACT,OAAO,CAAE,CAAC,CAeX,AAhBD,AAGE,UAHQ,CAGR,UAAU,AAAC,CACT,aAAa,CAAE,IAAI,CACnB,WAAW,CAAE,CAAC,CACd,eAAe,CAAE,IAAI,CAStB,AAfH,AAQI,UARM,CAGR,UAAU,CAKR,KAAK,AAAC,CACJ,OAAO,CAAE,KAAK,CACd,YAAY,CAAE,IAAI,CAClB,SAAS,CAAE,KAAK,CAChB,KAAK,CRNE,IAAI,CQOX,SAAS,CAAE,IAAI,CAChB,AAGL,MAAM,mBAEF,CADF,AACE,UADQ,CACR,UAAU,AAAC,CACT,OAAO,CAAE,IAAI,CACb,aAAa,CAAE,GAAG,CAKnB,AARH,AAKI,UALM,CACR,UAAU,CAIR,KAAK,AAAC,CACJ,UAAU,CAAE,IAAI,CACjB,CACF,AAGL,AAAA,aAAa,AAAC,CACZ,OAAO,CAAE,CAAC,CACV,UAAU,CAAE,IAAI,CAQjB,AAVD,AAIE,aAJW,CAIX,aAAa,AAAC,CACZ,aAAa,CAAE,GAAG,CAInB,AATH,AAMI,aANS,CAIX,aAAa,CAEX,CAAC,AAAC,CACA,OAAO,CAAE,MAAM,CAChB,ACrCL,AAEI,OAFG,CACL,MAAM,CACJ,UAAU,AAAC,CACT,UAAU,CAAE,CAAC,CACb,aAAa,CAAE,CAAC,CAChB,cAAc,CAAE,IAAI,CACpB,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,IAAI,CAClB,AARL,AASI,OATG,CACL,MAAM,CAQJ,KAAK,AAAC,CACJ,UAAU,CAAE,CAAC,CACb,aAAa,CAAE,IAAI,CACpB,AAZL,AAaI,OAbG,CACL,MAAM,CAYJ,KAAK,CAAC,CAAC,AAAC,CACN,KAAK,CTJM,OAAO,CSKlB,SAAS,CAAE,MAAM,CAClB,AAhBL,AAiBI,OAjBG,CACL,MAAM,CAgBJ,OAAO,AAAC,CACN,cAAc,CAAE,SAAS,CACzB,cAAc,CAAE,KAAK,CACrB,WAAW,CAAE,GAAG,CACjB,AArBL,AAsBI,OAtBG,CACL,MAAM,CAqBJ,SAAS,AAAC,CACR,OAAO,CAAE,MAAM,CAChB,AAxBL,AA4BM,OA5BC,CA0BL,QAAQ,CACN,EAAE,CACE,MAAM,AAAC,CACP,QAAQ,CAAE,QAAQ,CAClB,GAAG,CAAE,IAAI,CACT,IAAI,CAAE,KAAK,CACX,KAAK,CTpBI,OAAO,CSqBhB,OAAO,CAAE,GAAG,CACZ,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,MAAM,CAClB,AApCP,AAuCE,OAvCK,CAuCL,QAAQ,CAAC,GAAG,CAvCd,OAAO,CAwCL,QAAQ,CAAC,KAAK,AAAC,CACb,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,IAAI,CACZ,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAI,CAmFb,AA/HH,AA+CI,OA/CG,CAuCL,QAAQ,CAAC,GAAG,CAQV,gBAAgB,CA/CpB,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAOZ,gBAAgB,AAAC,CACf,QAAQ,CAAE,QAAQ,CAClB,QAAQ,CAAE,MAAM,CAChB,WAAW,CAAE,QAAQ,CAErB,MAAM,CAAE,CAAC,CAYV,AAhEL,AAsDM,OAtDC,CAuCL,QAAQ,CAAC,GAAG,CAQV,gBAAgB,CAOd,MAAM,CAtDZ,OAAO,CAuCL,QAAQ,CAAC,GAAG,CAQV,gBAAgB,CAQd,MAAM,CAvDZ,OAAO,CAuCL,QAAQ,CAAC,GAAG,CAQV,gBAAgB,CASd,KAAK,CAxDX,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAOZ,gBAAgB,CAOd,MAAM,CAtDZ,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAOZ,gBAAgB,CAQd,MAAM,CAvDZ,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAOZ,gBAAgB,CASd,KAAK,AAAC,CACJ,QAAQ,CAAE,QAAQ,CAClB,GAAG,CAAE,CAAC,CACN,IAAI,CAAE,CAAC,CACP,UAAU,CAAE,CAAC,CACb,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACb,AA/DP,AAiEI,OAjEG,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAjEd,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,AAAC,CACT,MAAM,CAAE,SAAS,CACjB,OAAO,CAAE,SAAS,CAClB,UAAU,CAAE,OAAO,CACnB,KAAK,CTxDG,OAAO,CSyDf,MAAM,CAAE,+BAA+B,CACvC,WAAW,CAAE,IAAI,CAiClB,AAxGL,AAyEM,OAzEC,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAQR,CAAC,CAzEP,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAQR,CAAC,AAAC,CACA,MAAM,CAAE,CAAC,CACV,AA3EP,AA4EM,OA5EC,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAWN,MAAM,CA5Ed,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAWN,MAAM,AAAC,CACP,YAAY,CAAE,KAAK,CACnB,KAAK,CTjEC,OAAO,CSkEb,OAAO,CAAE,OAAO,CAChB,cAAc,CAAE,KAAK,CACrB,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,IAAI,CAClB,AAnFP,AAoFM,OApFC,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAmBR,MAAM,CApFZ,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAmBR,MAAM,AAAC,CACL,MAAM,CAAE,aAAa,CACrB,KAAK,CThFA,IAAI,CSiFT,SAAS,CAAE,IAAI,CAgBhB,AAvGP,AAyFQ,OAzFD,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAmBR,MAAM,CAKJ,CAAC,CAzFT,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAmBR,MAAM,CAKJ,CAAC,AAAC,CACA,gBAAgB,CAAE,6DAA2E,CAC7F,KAAK,CTrFF,IAAI,CSsFR,AA5FT,AA6FQ,OA7FD,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAmBR,MAAM,CASJ,CAAC,CAAC,KAAK,CA7Ff,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAmBR,MAAM,CASJ,CAAC,CAAC,KAAK,AAAC,CACN,gBAAgB,CAAE,6DAAuG,CACzH,KAAK,CTzFF,IAAI,CS0FR,AAhGT,AAkGU,OAlGH,CAuCL,QAAQ,CAAC,GAAG,CA0BV,UAAU,CAmBR,MAAM,CAaJ,IAAI,CACA,MAAM,CAlGlB,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAyBZ,UAAU,CAmBR,MAAM,CAaJ,IAAI,CACA,MAAM,AAAC,CACP,OAAO,CAAE,MAAM,CACf,OAAO,CAAE,GAAG,CACb,AArGX,AAyGI,OAzGG,CAuCL,QAAQ,CAAC,GAAG,CAkEV,UAAU,CAzGd,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAiEZ,UAAU,AAAC,CACT,MAAM,CAAE,CAAC,CACT,KAAK,CAAE,GAAG,CACV,UAAU,CAAE,IAAI,CAUjB,AAtHL,AA8GM,OA9GC,CAuCL,QAAQ,CAAC,GAAG,CAkEV,UAAU,AAKP,KAAK,CA9GZ,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAiEZ,UAAU,AAKP,KAAK,AAAC,CACL,YAAY,CAAE,GAAG,CACjB,WAAW,CAAE,IAAI,CAClB,AAjHP,AAkHM,OAlHC,CAuCL,QAAQ,CAAC,GAAG,CAkEV,UAAU,AASP,MAAM,CAlHb,OAAO,CAwCL,QAAQ,CAAC,KAAK,CAiEZ,UAAU,AASP,MAAM,AAAC,CACN,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,GAAG,CACjB,AArHP,AAuHI,OAvHG,CAuCL,QAAQ,CAAC,GAAG,CAgFV,QAAQ,CAvHZ,OAAO,CAwCL,QAAQ,CAAC,KAAK,CA+EZ,QAAQ,AAAC,CACP,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,IAAI,CAChB,KAAK,CTrHE,IAAI,CSsHX,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,IAAI,CAChB,AAGL,AAAA,UAAU,AAAC,CACT,cAAc,CAAE,IAAI,CACpB,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,IAAI,CAClB,AACD,AAEI,YAFQ,CACV,SAAS,CACL,MAAM,AAAC,CACP,OAAO,CAAE,GAAG,CP9HhB,gBAAgB,CAAE,qEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,CO6HxB,AAGL,AACE,iBADe,CACf,cAAc,AAAC,CPpIf,gBAAgB,CAAE,qEAAqE,CACvF,mBAAmB,CAAE,MAAM,CAC3B,eAAe,CAAE,QAAQ,CACzB,iBAAiB,CAAE,QAAQ,COmI1B,AAEH,MAAM,mBACJ,CAAA,AAAA,kBAAkB,CAClB,YAAY,CACZ,iBAAiB,AAAC,CAChB,OAAO,CAAE,MAAM,CAKhB,AARD,AAKE,kBALgB,CAKd,MAAM,CAJV,YAAY,CAIR,MAAM,CAHV,iBAAiB,CAGb,MAAM,AAAC,CACP,OAAO,CAAE,GAAG,CACb,CACF,AC5JH,AACE,QADM,CACN,UAAU,AAAC,CACT,OAAO,CAAE,CAAC,CAeX,AAjBH,AAII,QAJI,CACN,UAAU,CAGR,UAAU,AAAC,CACT,aAAa,CAAE,IAAI,CACnB,WAAW,CAAE,CAAC,CACd,eAAe,CAAE,IAAI,CAStB,AAhBL,AASM,QATE,CACN,UAAU,CAGR,UAAU,CAKR,KAAK,AAAC,CACJ,OAAO,CAAE,KAAK,CACd,YAAY,CAAE,IAAI,CAClB,SAAS,CAAE,KAAK,CAChB,KAAK,CVPA,IAAI,CUQT,SAAS,CAAE,IAAI,CAChB,AAGL,MAAM,mBAEF,CApBN,AAoBM,QApBE,CAmBJ,UAAU,CACR,UAAU,AAAC,CACT,OAAO,CAAE,IAAI,CACb,aAAa,CAAE,GAAG,CAClB,WAAW,CAAE,IAAI,CAKlB,AA5BP,AAyBQ,QAzBA,CAmBJ,UAAU,CACR,UAAU,CAKR,KAAK,AAAC,CACJ,UAAU,CAAE,IAAI,CACjB,CACF,AC5BP,AAAA,mBAAmB,AAAC,CAClB,UAAU,CAAE,IAAI,CACjB,ACFD,AAAA,OAAO,AAAC,CACN,QAAQ,CAAE,QAAQ,CAClB,MAAM,CAAE,CAAC,CACT,aAAa,CAAE,IAAI,CACnB,KAAK,CAAE,IAAI,CACX,KAAK,CZCM,IAAI,CYAf,cAAc,CAAE,GAAG,CACnB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,IAAI,CAuChB,AA/CD,AAUE,OAVK,CAUL,EAAE,AAAC,CACD,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,UAAU,CAAE,IAAI,CACjB,AAdH,AAeE,OAfK,CAeL,EAAE,AAAC,CACD,OAAO,CAAE,YAAY,CACrB,YAAY,CAAE,IAAI,CAClB,YAAY,CAAE,SAAS,CACvB,YAAY,CZdD,IAAI,CYef,cAAc,CAAE,MAAM,CAKvB,AAzBH,AAsBI,OAtBG,CAeL,EAAE,CAOA,CAAC,AAAC,CACA,YAAY,CAAE,IAAI,CACnB,AAxBL,AA0BE,OA1BK,CA0BL,EAAE,CAAC,UAAU,AAAC,CACZ,YAAY,CAAE,CAAC,CACf,YAAY,CAAE,CAAC,CAKhB,AAjCH,AA8BI,OA9BG,CA0BL,EAAE,CAAC,UAAU,CAIX,CAAC,AAAC,CACA,YAAY,CAAE,CAAC,CAChB,AAhCL,AAkCE,OAlCK,CAkCL,CAAC,AAAC,CACA,KAAK,CZ7BI,IAAI,CY8Bb,eAAe,CAAE,SAAS,CAC1B,gBAAgB,CAAE,IAAI,CACvB,AAtCH,AAuCE,OAvCK,CAuCL,CAAC,CAAC,KAAK,AAAC,CACN,KAAK,CZlCI,IAAI,CYmCd,AAzCH,AA0CE,OA1CK,CA0CL,YAAY,AAAC,CACX,MAAM,CAAE,IAAI,CACZ,cAAc,CAAE,MAAM,CACtB,WAAW,CAAE,IAAI,CAClB,AAEH,MAAM,mBACJ,CAAA,AAAA,OAAO,AAAC,CACN,OAAO,CAAE,IAAI,CACb,SAAS,CAAE,QAAQ,CACnB,eAAe,CAAE,aAAa,CAC9B,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,MAAM,CACrB,aAAa,CAAE,IAAI,CASpB,AAfD,AAQE,OARK,CAQL,YAAY,AAAC,CACX,UAAU,CAAE,UAAU,CACtB,YAAY,CAAE,IAAI,CACnB,AAXH,AAYE,OAZK,CAYL,aAAa,AAAC,CACZ,UAAU,CAAE,QAAQ,CACrB,CACF,AChEH,AAAA,WAAW,AAAC,CACV,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,MAAM,CAoBnB,AAxBD,AAME,WANS,CAMT,YAAY,AAAC,CACX,KAAK,CbEI,OAAO,CaDhB,SAAS,CAAE,KAAK,CACjB,AATH,AAUE,WAVS,CAUT,CAAC,AAAC,CACA,OAAO,CAAE,OAAO,CAChB,aAAa,CAAE,GAAG,CAElB,gBAAgB,CAAE,IAAI,CACtB,KAAK,CbNI,OAAO,CaOhB,eAAe,CAAE,IAAI,CACtB,AAjBH,AAkBE,WAlBS,CAkBT,CAAC,CAAC,KAAK,AAAC,CACN,gBAAgB,CAAE,IAAI,CACvB,AApBH,AAqBE,WArBS,CAqBT,CAAC,CAAC,KAAK,CAAA,GAAK,CAAA,OAAO,CAAE,CACnB,KAAK,CbXQ,OAAO,CaYrB,ACvBH,AAAA,aAAa,AAAC,CACZ,OAAO,CAAE,OAAO,CAChB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,KAAK,CAAC,GAAG,CdMF,OAAO,CcLtB,aAAa,CAAE,GAAG,CAClB,gBAAgB,CdLC,IAAO,CcMxB,KAAK,CdEM,OAAO,CcDlB,SAAS,CAAE,MAAM,CACjB,qBAAqB,CAAE,GAAG,CAC1B,kBAAkB,CAAE,GAAG,CAKxB,AAfD,AAYE,aAZW,CAYT,KAAK,AAAC,CACN,MAAM,CAAE,KAAK,CAAC,GAAG,CdDJ,OAAO,CcErB,AAEH,AACE,cADY,CACZ,EAAE,AAAA,mBAAmB,AAAC,CACpB,OAAO,CAAE,CAAC,CACV,eAAe,CAAE,IAAI,CACtB,AAJH,AAKE,cALY,CAKZ,EAAE,AAAC,CACD,MAAM,CAAE,QAAQ,CACjB,AAPH,AAQE,cARY,CAQZ,CAAC,AAAA,oBAAoB,AAAC,CACpB,gBAAgB,CAAE,IAAI,CACtB,KAAK,CdjBI,OAAO,CckBhB,cAAc,CAAE,UAAU,CAC1B,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,GAAG,CACjB,AAdH,AAeE,cAfY,CAeZ,CAAC,AAAA,cAAc,AAAC,CACd,QAAQ,CAAE,MAAM,CAChB,MAAM,CAAE,SAAS,CACjB,UAAU,CAAE,IAAI,CAChB,UAAU,CAAE,OAAO,CACnB,SAAS,CAAE,IAAI,CAChB,AArBH,AAsBE,cAtBY,CAsBZ,EAAE,AAAA,eAAe,AAAC,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,Cd/BhB,OAAsB,CcgC/B,KAAK,CdhCI,OAAsB,CciC/B,WAAW,CAAE,IAAI,CAClB,AAEH,AAAA,iBAAiB,AAAC,CAChB,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,IAAI,CACpB,KAAK,CdtCM,OAAO,CcuCnB,AChDD,AACE,UADQ,CACR,gBAAgB,AAAC,CACf,KAAK,CfII,IAAI,CeHd,AAHH,AAIE,UAJQ,CAIR,eAAe,AAAC,CACd,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,MAAM,CAKnB,AAXH,AAOI,UAPM,CAIR,eAAe,CAGb,CAAC,AAAC,CACA,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,IAAI,CACb,ACTL,AAAA,WAAW,AAAC,CACV,QAAQ,CAAE,QAAQ,CACnB,AAED,AAAA,WAAW,EAAE,KAAK,AAAC,CACjB,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,OAAO,CAChB,OAAO,CAAE,IAAI,CACb,OAAO,CAAE,SAAS,CAClB,sBAAsB,CAAE,oBAAoB,CAC5C,KAAK,ChBVY,IAAO,CgBWxB,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,GAAG,CAChB,SAAS,CAAE,MAAgB,CAC3B,WAAW,CjBdM,gBAAgB,CAAE,SAAS,CiBe5C,WAAW,CjBXC,KAAK,CiBYjB,cAAc,CAAE,kBAAkB,CAClC,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,UAAU,CACrB,WAAW,CAAE,GAAG,CAChB,OAAO,CAAE,gBAAgB,CACzB,UAAU,ChBbC,OAAO,CgBclB,aAAa,CAAE,GAAG,CAClB,OAAO,CAAE,CAAC,CACX,AAED,AAAA,WAAW,EAAE,MAAM,AAAC,CAClB,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,OAAO,CAChB,OAAO,CAAE,IAAI,CACb,KAAK,CAAE,CAAC,CACR,MAAM,CAAE,CAAC,CACT,KAAK,ChBxBM,OAAO,CgByBlB,cAAc,CAAE,IAAI,CACpB,OAAO,CAAE,EAAE,CACX,MAAM,CAAE,qBAAqB,CAC7B,OAAO,CAAE,CAAC,CACX,AAED,UAAU,CAAV,cAAU,CACR,IAAI,CACF,OAAO,CAAE,CAAC,CAEZ,EAAE,CACA,OAAO,CAAE,CAAC,EAKd,AAGE,WAHS,CAAC,KAAK,EAGZ,MAAM,CAHX,WAAW,CAAC,KAAK,EAIZ,KAAK,CAHV,WAAW,CAAC,MAAM,EAEb,MAAM,CAFX,WAAW,CAAC,MAAM,EAGb,KAAK,CAFV,WAAW,CAAC,KAAK,EACZ,MAAM,CADX,WAAW,CAAC,KAAK,EAEZ,KAAK,AAAC,CACP,OAAO,CAAE,YAAY,CACrB,eAAe,CAAE,IAAI,CACrB,cAAc,CAAE,cAAc,CAC9B,kBAAkB,CAAE,IAAI,CACxB,mBAAmB,CAAE,QAAQ,CAC7B,yBAAyB,CAAE,OAAO,CACnC,AAGH,AAEE,aAFW,EAER,KAAK,CADV,cAAc,EACT,KAAK,AAAC,CACP,GAAG,CAAE,IAAI,CACT,KAAK,CAAE,GAAG,CACV,UAAU,CAAE,GAAG,CAChB,AANH,AAOE,aAPW,EAOR,MAAM,CANX,cAAc,EAMT,MAAM,AAAC,CACR,GAAG,CAAE,IAAI,CACT,KAAK,CAAE,GAAG,CACV,MAAM,CAAE,IAAI,CACZ,YAAY,CAAE,IAAI,CAClB,mBAAmB,ChBnEV,OAAO,CgBoEjB,AAEH,AAAA,cAAc,EAAE,KAAK,AAAC,CACpB,YAAY,CAAE,KAAK,CACpB,AAED,AAAA,aAAa,EAAE,KAAK,AAAC,CACnB,SAAS,CAAE,eAAe,CAC3B,ACrFD,AACE,WADS,CACT,oBAAoB,AAAC,CACnB,KAAK,CjBII,IAAI,CiBHd,AAHH,AAMM,WANK,CAIT,cAAc,CACZ,mBAAmB,CACjB,oBAAoB,AAAC,CACnB,KAAK,CjBDA,IAAI,CiBEV,AARP,AASM,WATK,CAIT,cAAc,CACZ,mBAAmB,CAIjB,oBAAoB,CAAC,MAAM,AAAC,CAC1B,OAAO,CAAE,IAAI,CACd,AAXP,AAYM,WAZK,CAIT,cAAc,CACZ,mBAAmB,CAOjB,oBAAoB,CAAC,KAAK,AAAC,CACzB,OAAO,CAAE,GAAG,CACb,AnBwIP,AAAA,GAAG,AAAC,CACF,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,mBAAmB,CAC5B,MAAM,CAAE,GAAG,CAAC,MAAM,CEpJL,IAAI,CFqJjB,aAAa,CAAE,GAAG,CAClB,qBAAqB,CAAE,GAAG,CAC1B,SAAS,CAAE,IAAI,CACf,WAAW,CC3JM,gBAAgB,CAAE,SAAS,CD4J5C,WAAW,CAAE,IAAI,CACjB,QAAQ,CAAE,QAAQ,CA+BnB,AAxCD,AAWE,GAXC,CAWD,cAAc,AAAC,CACb,QAAQ,CAAE,QAAQ,CAClB,GAAG,CAAE,CAAC,CACN,KAAK,CAAE,CAAC,CACR,MAAM,CAAE,CAAC,CACT,aAAa,CAAE,KAAK,CACpB,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,2BAA2B,CACxC,WAAW,CAAE,GAAG,CAChB,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,GAAG,CAChB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,OAAO,CACzB,SAAS,CAAE,IAAI,CACf,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,OAAO,CACf,cAAc,CAAE,GAAG,CACpB,AA5BH,AA8BE,GA9BC,CA8BD,cAAc,CAAC,KAAK,AAAC,CACnB,gBAAgB,CAAE,IAAI,CACtB,KAAK,CAAE,OAAO,CACf,AAjCH,AAmCE,GAnCC,CAmCD,IAAI,AAAC,CACH,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,CAAC,CACV,MAAM,CAAE,IAAI,CACb,AAGH,AAAA,IAAI,AAAC,CACH,WAAW,CC/LM,gBAAgB,CAAE,SAAS,CDgM5C,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CAAC,MAAM,CE9LL,IAAI,CF+LjB,aAAa,CAAE,GAAG,CAClB,qBAAqB,CAAE,GAAG,CAC3B,AAED,AAEE,UAFQ,CAEJ,GAAG,AAAC,CACN,aAAa,CAAE,GAAG,CAClB,qBAAqB,CAAE,GAAG,CAC3B,AALH,AAOE,UAPQ,CAOR,GAAG,AAAC,CACF,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,IAAI,CACjB,AAVH,AAcI,UAdM,CAYR,KAAK,CAEH,GAAG,AAAC,CACF,UAAU,CAAE,CAAC,CACd,AAhBL,AAmBM,UAnBI,CAYR,KAAK,CAMH,EAAE,CAAC,WAAW,CACZ,GAAG,AAAC,CACF,aAAa,CAAE,CAAC,CACjB,AArBP,AAyBM,UAzBI,CAYR,KAAK,CAYH,EAAE,CAAC,UAAU,CACX,GAAG,AAAC,CACF,YAAY,CAAE,CAAC,CAChB" +} \ No newline at end of file diff --git a/public/images/favicon.ico b/public/images/favicon.ico new file mode 100644 index 0000000..84a85d3 Binary files /dev/null and b/public/images/favicon.ico differ diff --git a/public/images/logo.png b/public/images/logo.png new file mode 100644 index 0000000..43a6ef0 Binary files /dev/null and b/public/images/logo.png differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..afacee4 --- /dev/null +++ b/public/index.html @@ -0,0 +1,211 @@ + + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + +

Find me on + + + + + + + + , + + + + + + + , + + + + + + + and + + + + + + + . + +

+ + +
+ +
+ Writings + + Topics + + + + go + + golang + + handler + + http + + middleware + + proxy + + reverse-proxy + + + Most recent + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + +
+ + + + + + diff --git a/public/index.xml b/public/index.xml new file mode 100644 index 0000000..116f14d --- /dev/null +++ b/public/index.xml @@ -0,0 +1,53 @@ + + + + Basit's Blog + https://blog.rjbasitali.com/ + Recent content on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + Contact + https://blog.rjbasitali.com/contact/ + Sun, 01 Aug 2021 16:26:01 +0500 + + https://blog.rjbasitali.com/contact/ + If you’ve got any questions, suggestions or would like to discuss a project then email me at rjbasitali@gmail.com. I’d be happy to hear from you. +You can also find me on LinkedIn, Github and Instagram. + + + + About + https://blog.rjbasitali.com/about/ + Sat, 31 Jul 2021 22:39:25 +0500 + + https://blog.rjbasitali.com/about/ + Hi, I&rsquo;m Basit Ali. I&rsquo;m a software developer specializing in Java, Go and Android. +Previously I&rsquo;ve worked with many startups including telehealth, trivia games, logistics and more. Right now I&rsquo;m working on providing video conferencing and other VoIP solutions using WebRTC, Golang and other cool technologies. +I generally work with Go and Java for backend, React, Android, Git, Postgres and Linux, the technologies, especially databases can change depending on the needs of the project. + + + + diff --git a/public/js/code-copy.js b/public/js/code-copy.js new file mode 100644 index 0000000..5a07bf8 --- /dev/null +++ b/public/js/code-copy.js @@ -0,0 +1,36 @@ +(() => { + + function createCopyButton(codeNode) { + const copyBtn = document.createElement('button') + copyBtn.className = 'code-copy-btn' + copyBtn.type = 'button' + copyBtn.innerText = 'copy' + + let resetTimer + copyBtn.addEventListener('click', () => { + navigator.clipboard.writeText(codeNode.innerText).then(() => { + copyBtn.innerText = 'copied!' + }).then(() => { + clearTimeout(resetTimer) + resetTimer = setTimeout(() => { + copyBtn.innerText = 'copy' + }, 1000) + }) + }) + + return copyBtn + } + + document.querySelectorAll('pre > code') + .forEach((codeNode) => { + const copyBtn = createCopyButton(codeNode); + const preNode = codeNode.parentNode + codeNode.parentNode.insertBefore(copyBtn, codeNode) + }) + + document.querySelectorAll('.highlight table > tbody > tr > td:first-child .code-copy-btn') + .forEach((btn) => { + btn.remove() + }) + +})() \ No newline at end of file diff --git a/public/js/feather.min.js b/public/js/feather.min.js new file mode 100644 index 0000000..156cd61 --- /dev/null +++ b/public/js/feather.min.js @@ -0,0 +1,13 @@ +!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.feather=n():e.feather=n()}("undefined"!=typeof self?self:this,function(){return function(e){var n={};function i(t){if(n[t])return n[t].exports;var l=n[t]={i:t,l:!1,exports:{}};return e[t].call(l.exports,l,l.exports,i),l.l=!0,l.exports}return i.m=e,i.c=n,i.d=function(e,n,t){i.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:t})},i.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},i.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(n,"a",n),n},i.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},i.p="",i(i.s=80)}([function(e,n,i){(function(n){var i="object",t=function(e){return e&&e.Math==Math&&e};e.exports=t(typeof globalThis==i&&globalThis)||t(typeof window==i&&window)||t(typeof self==i&&self)||t(typeof n==i&&n)||Function("return this")()}).call(this,i(75))},function(e,n){var i={}.hasOwnProperty;e.exports=function(e,n){return i.call(e,n)}},function(e,n,i){var t=i(0),l=i(11),r=i(33),o=i(62),a=t.Symbol,c=l("wks");e.exports=function(e){return c[e]||(c[e]=o&&a[e]||(o?a:r)("Symbol."+e))}},function(e,n,i){var t=i(6);e.exports=function(e){if(!t(e))throw TypeError(String(e)+" is not an object");return e}},function(e,n){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,n,i){var t=i(8),l=i(7),r=i(10);e.exports=t?function(e,n,i){return l.f(e,n,r(1,i))}:function(e,n,i){return e[n]=i,e}},function(e,n){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,n,i){var t=i(8),l=i(35),r=i(3),o=i(18),a=Object.defineProperty;n.f=t?a:function(e,n,i){if(r(e),n=o(n,!0),r(i),l)try{return a(e,n,i)}catch(e){}if("get"in i||"set"in i)throw TypeError("Accessors not supported");return"value"in i&&(e[n]=i.value),e}},function(e,n,i){var t=i(4);e.exports=!t(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,n){e.exports={}},function(e,n){e.exports=function(e,n){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:n}}},function(e,n,i){var t=i(0),l=i(19),r=i(17),o=t["__core-js_shared__"]||l("__core-js_shared__",{});(e.exports=function(e,n){return o[e]||(o[e]=void 0!==n?n:{})})("versions",[]).push({version:"3.1.3",mode:r?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=o(i(43)),l=o(i(41)),r=o(i(40));function o(e){return e&&e.__esModule?e:{default:e}}n.default=Object.keys(l.default).map(function(e){return new t.default(e,l.default[e],r.default[e])}).reduce(function(e,n){return e[n.name]=n,e},{})},function(e,n){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(e,n,i){var t=i(72),l=i(20);e.exports=function(e){return t(l(e))}},function(e,n){e.exports={}},function(e,n,i){var t=i(11),l=i(33),r=t("keys");e.exports=function(e){return r[e]||(r[e]=l(e))}},function(e,n){e.exports=!1},function(e,n,i){var t=i(6);e.exports=function(e,n){if(!t(e))return e;var i,l;if(n&&"function"==typeof(i=e.toString)&&!t(l=i.call(e)))return l;if("function"==typeof(i=e.valueOf)&&!t(l=i.call(e)))return l;if(!n&&"function"==typeof(i=e.toString)&&!t(l=i.call(e)))return l;throw TypeError("Can't convert object to primitive value")}},function(e,n,i){var t=i(0),l=i(5);e.exports=function(e,n){try{l(t,e,n)}catch(i){t[e]=n}return n}},function(e,n){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,n){var i=Math.ceil,t=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?t:i)(e)}},function(e,n,i){var t; +/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +!function(){"use strict";var i=function(){function e(){}function n(e,n){for(var i=n.length,t=0;t0?l(t(e),9007199254740991):0}},function(e,n,i){var t=i(1),l=i(14),r=i(68),o=i(15),a=r(!1);e.exports=function(e,n){var i,r=l(e),c=0,p=[];for(i in r)!t(o,i)&&t(r,i)&&p.push(i);for(;n.length>c;)t(r,i=n[c++])&&(~a(p,i)||p.push(i));return p}},function(e,n,i){var t=i(0),l=i(11),r=i(5),o=i(1),a=i(19),c=i(36),p=i(37),y=p.get,h=p.enforce,x=String(c).split("toString");l("inspectSource",function(e){return c.call(e)}),(e.exports=function(e,n,i,l){var c=!!l&&!!l.unsafe,p=!!l&&!!l.enumerable,y=!!l&&!!l.noTargetGet;"function"==typeof i&&("string"!=typeof n||o(i,"name")||r(i,"name",n),h(i).source=x.join("string"==typeof n?n:"")),e!==t?(c?!y&&e[n]&&(p=!0):delete e[n],p?e[n]=i:r(e,n,i)):p?e[n]=i:a(n,i)})(Function.prototype,"toString",function(){return"function"==typeof this&&y(this).source||c.call(this)})},function(e,n){var i={}.toString;e.exports=function(e){return i.call(e).slice(8,-1)}},function(e,n,i){var t=i(8),l=i(73),r=i(10),o=i(14),a=i(18),c=i(1),p=i(35),y=Object.getOwnPropertyDescriptor;n.f=t?y:function(e,n){if(e=o(e),n=a(n,!0),p)try{return y(e,n)}catch(e){}if(c(e,n))return r(!l.f.call(e,n),e[n])}},function(e,n,i){var t=i(0),l=i(31).f,r=i(5),o=i(29),a=i(19),c=i(71),p=i(65);e.exports=function(e,n){var i,y,h,x,s,u=e.target,d=e.global,f=e.stat;if(i=d?t:f?t[u]||a(u,{}):(t[u]||{}).prototype)for(y in n){if(x=n[y],h=e.noTargetGet?(s=l(i,y))&&s.value:i[y],!p(d?y:u+(f?".":"#")+y,e.forced)&&void 0!==h){if(typeof x==typeof h)continue;c(x,h)}(e.sham||h&&h.sham)&&r(x,"sham",!0),o(i,y,x,e)}}},function(e,n){var i=0,t=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++i+t).toString(36))}},function(e,n,i){var t=i(0),l=i(6),r=t.document,o=l(r)&&l(r.createElement);e.exports=function(e){return o?r.createElement(e):{}}},function(e,n,i){var t=i(8),l=i(4),r=i(34);e.exports=!t&&!l(function(){return 7!=Object.defineProperty(r("div"),"a",{get:function(){return 7}}).a})},function(e,n,i){var t=i(11);e.exports=t("native-function-to-string",Function.toString)},function(e,n,i){var t,l,r,o=i(76),a=i(0),c=i(6),p=i(5),y=i(1),h=i(16),x=i(15),s=a.WeakMap;if(o){var u=new s,d=u.get,f=u.has,g=u.set;t=function(e,n){return g.call(u,e,n),n},l=function(e){return d.call(u,e)||{}},r=function(e){return f.call(u,e)}}else{var v=h("state");x[v]=!0,t=function(e,n){return p(e,v,n),n},l=function(e){return y(e,v)?e[v]:{}},r=function(e){return y(e,v)}}e.exports={set:t,get:l,has:r,enforce:function(e){return r(e)?l(e):t(e,{})},getterFor:function(e){return function(n){var i;if(!c(n)||(i=l(n)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return i}}}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=Object.assign||function(e){for(var n=1;n0&&void 0!==arguments[0]?arguments[0]:{};if("undefined"==typeof document)throw new Error("`feather.replace()` only works in a browser environment.");var n=document.querySelectorAll("[data-feather]");Array.from(n).forEach(function(n){return function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=function(e){return Array.from(e.attributes).reduce(function(e,n){return e[n.name]=n.value,e},{})}(e),o=i["data-feather"];delete i["data-feather"];var a=r.default[o].toSvg(t({},n,i,{class:(0,l.default)(n.class,i.class)})),c=(new DOMParser).parseFromString(a,"image/svg+xml").querySelector("svg");e.parentNode.replaceChild(c,e)}(n,e)})}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t,l=i(12),r=(t=l)&&t.__esModule?t:{default:t};n.default=function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(console.warn("feather.toSvg() is deprecated. Please use feather.icons[name].toSvg() instead."),!e)throw new Error("The required `key` (icon name) parameter is missing.");if(!r.default[e])throw new Error("No icon matching '"+e+"'. See the complete list of icons at https://feathericons.com");return r.default[e].toSvg(n)}},function(e){e.exports={activity:["pulse","health","action","motion"],airplay:["stream","cast","mirroring"],"alert-circle":["warning","alert","danger"],"alert-octagon":["warning","alert","danger"],"alert-triangle":["warning","alert","danger"],"align-center":["text alignment","center"],"align-justify":["text alignment","justified"],"align-left":["text alignment","left"],"align-right":["text alignment","right"],anchor:[],archive:["index","box"],"at-sign":["mention","at","email","message"],award:["achievement","badge"],aperture:["camera","photo"],"bar-chart":["statistics","diagram","graph"],"bar-chart-2":["statistics","diagram","graph"],battery:["power","electricity"],"battery-charging":["power","electricity"],bell:["alarm","notification","sound"],"bell-off":["alarm","notification","silent"],bluetooth:["wireless"],"book-open":["read","library"],book:["read","dictionary","booklet","magazine","library"],bookmark:["read","clip","marker","tag"],box:["cube"],briefcase:["work","bag","baggage","folder"],calendar:["date"],camera:["photo"],cast:["chromecast","airplay"],circle:["off","zero","record"],clipboard:["copy"],clock:["time","watch","alarm"],"cloud-drizzle":["weather","shower"],"cloud-lightning":["weather","bolt"],"cloud-rain":["weather"],"cloud-snow":["weather","blizzard"],cloud:["weather"],codepen:["logo"],codesandbox:["logo"],code:["source","programming"],coffee:["drink","cup","mug","tea","cafe","hot","beverage"],columns:["layout"],command:["keyboard","cmd","terminal","prompt"],compass:["navigation","safari","travel","direction"],copy:["clone","duplicate"],"corner-down-left":["arrow","return"],"corner-down-right":["arrow"],"corner-left-down":["arrow"],"corner-left-up":["arrow"],"corner-right-down":["arrow"],"corner-right-up":["arrow"],"corner-up-left":["arrow"],"corner-up-right":["arrow"],cpu:["processor","technology"],"credit-card":["purchase","payment","cc"],crop:["photo","image"],crosshair:["aim","target"],database:["storage","memory"],delete:["remove"],disc:["album","cd","dvd","music"],"dollar-sign":["currency","money","payment"],droplet:["water"],edit:["pencil","change"],"edit-2":["pencil","change"],"edit-3":["pencil","change"],eye:["view","watch"],"eye-off":["view","watch","hide","hidden"],"external-link":["outbound"],facebook:["logo","social"],"fast-forward":["music"],figma:["logo","design","tool"],"file-minus":["delete","remove","erase"],"file-plus":["add","create","new"],"file-text":["data","txt","pdf"],film:["movie","video"],filter:["funnel","hopper"],flag:["report"],"folder-minus":["directory"],"folder-plus":["directory"],folder:["directory"],framer:["logo","design","tool"],frown:["emoji","face","bad","sad","emotion"],gift:["present","box","birthday","party"],"git-branch":["code","version control"],"git-commit":["code","version control"],"git-merge":["code","version control"],"git-pull-request":["code","version control"],github:["logo","version control"],gitlab:["logo","version control"],globe:["world","browser","language","translate"],"hard-drive":["computer","server","memory","data"],hash:["hashtag","number","pound"],headphones:["music","audio","sound"],heart:["like","love","emotion"],"help-circle":["question mark"],hexagon:["shape","node.js","logo"],home:["house","living"],image:["picture"],inbox:["email"],instagram:["logo","camera"],key:["password","login","authentication","secure"],layers:["stack"],layout:["window","webpage"],"life-bouy":["help","life ring","support"],link:["chain","url"],"link-2":["chain","url"],linkedin:["logo","social media"],list:["options"],lock:["security","password","secure"],"log-in":["sign in","arrow","enter"],"log-out":["sign out","arrow","exit"],mail:["email","message"],"map-pin":["location","navigation","travel","marker"],map:["location","navigation","travel"],maximize:["fullscreen"],"maximize-2":["fullscreen","arrows","expand"],meh:["emoji","face","neutral","emotion"],menu:["bars","navigation","hamburger"],"message-circle":["comment","chat"],"message-square":["comment","chat"],"mic-off":["record","sound","mute"],mic:["record","sound","listen"],minimize:["exit fullscreen","close"],"minimize-2":["exit fullscreen","arrows","close"],minus:["subtract"],monitor:["tv","screen","display"],moon:["dark","night"],"more-horizontal":["ellipsis"],"more-vertical":["ellipsis"],"mouse-pointer":["arrow","cursor"],move:["arrows"],music:["note"],navigation:["location","travel"],"navigation-2":["location","travel"],octagon:["stop"],package:["box","container"],paperclip:["attachment"],pause:["music","stop"],"pause-circle":["music","audio","stop"],"pen-tool":["vector","drawing"],percent:["discount"],"phone-call":["ring"],"phone-forwarded":["call"],"phone-incoming":["call"],"phone-missed":["call"],"phone-off":["call","mute"],"phone-outgoing":["call"],phone:["call"],play:["music","start"],"pie-chart":["statistics","diagram"],"play-circle":["music","start"],plus:["add","new"],"plus-circle":["add","new"],"plus-square":["add","new"],pocket:["logo","save"],power:["on","off"],printer:["fax","office","device"],radio:["signal"],"refresh-cw":["synchronise","arrows"],"refresh-ccw":["arrows"],repeat:["loop","arrows"],rewind:["music"],"rotate-ccw":["arrow"],"rotate-cw":["arrow"],rss:["feed","subscribe"],save:["floppy disk"],scissors:["cut"],search:["find","magnifier","magnifying glass"],send:["message","mail","email","paper airplane","paper aeroplane"],settings:["cog","edit","gear","preferences"],"share-2":["network","connections"],shield:["security","secure"],"shield-off":["security","insecure"],"shopping-bag":["ecommerce","cart","purchase","store"],"shopping-cart":["ecommerce","cart","purchase","store"],shuffle:["music"],"skip-back":["music"],"skip-forward":["music"],slack:["logo"],slash:["ban","no"],sliders:["settings","controls"],smartphone:["cellphone","device"],smile:["emoji","face","happy","good","emotion"],speaker:["audio","music"],star:["bookmark","favorite","like"],"stop-circle":["media","music"],sun:["brightness","weather","light"],sunrise:["weather","time","morning","day"],sunset:["weather","time","evening","night"],tablet:["device"],tag:["label"],target:["logo","bullseye"],terminal:["code","command line","prompt"],thermometer:["temperature","celsius","fahrenheit","weather"],"thumbs-down":["dislike","bad","emotion"],"thumbs-up":["like","good","emotion"],"toggle-left":["on","off","switch"],"toggle-right":["on","off","switch"],tool:["settings","spanner"],trash:["garbage","delete","remove","bin"],"trash-2":["garbage","delete","remove","bin"],triangle:["delta"],truck:["delivery","van","shipping","transport","lorry"],tv:["television","stream"],twitch:["logo"],twitter:["logo","social"],type:["text"],umbrella:["rain","weather"],unlock:["security"],"user-check":["followed","subscribed"],"user-minus":["delete","remove","unfollow","unsubscribe"],"user-plus":["new","add","create","follow","subscribe"],"user-x":["delete","remove","unfollow","unsubscribe","unavailable"],user:["person","account"],users:["group"],"video-off":["camera","movie","film"],video:["camera","movie","film"],voicemail:["phone"],volume:["music","sound","mute"],"volume-1":["music","sound"],"volume-2":["music","sound"],"volume-x":["music","sound","mute"],watch:["clock","time"],"wifi-off":["disabled"],wifi:["connection","signal","wireless"],wind:["weather","air"],"x-circle":["cancel","close","delete","remove","times","clear"],"x-octagon":["delete","stop","alert","warning","times","clear"],"x-square":["cancel","close","delete","remove","times","clear"],x:["cancel","close","delete","remove","times","clear"],youtube:["logo","video","play"],"zap-off":["flash","camera","lightning"],zap:["flash","camera","lightning"],"zoom-in":["magnifying glass"],"zoom-out":["magnifying glass"]}},function(e){e.exports={activity:'',airplay:'',"alert-circle":'',"alert-octagon":'',"alert-triangle":'',"align-center":'',"align-justify":'',"align-left":'',"align-right":'',anchor:'',aperture:'',archive:'',"arrow-down-circle":'',"arrow-down-left":'',"arrow-down-right":'',"arrow-down":'',"arrow-left-circle":'',"arrow-left":'',"arrow-right-circle":'',"arrow-right":'',"arrow-up-circle":'',"arrow-up-left":'',"arrow-up-right":'',"arrow-up":'',"at-sign":'',award:'',"bar-chart-2":'',"bar-chart":'',"battery-charging":'',battery:'',"bell-off":'',bell:'',bluetooth:'',bold:'',"book-open":'',book:'',bookmark:'',box:'',briefcase:'',calendar:'',"camera-off":'',camera:'',cast:'',"check-circle":'',"check-square":'',check:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',"chevrons-down":'',"chevrons-left":'',"chevrons-right":'',"chevrons-up":'',chrome:'',circle:'',clipboard:'',clock:'',"cloud-drizzle":'',"cloud-lightning":'',"cloud-off":'',"cloud-rain":'',"cloud-snow":'',cloud:'',code:'',codepen:'',codesandbox:'',coffee:'',columns:'',command:'',compass:'',copy:'',"corner-down-left":'',"corner-down-right":'',"corner-left-down":'',"corner-left-up":'',"corner-right-down":'',"corner-right-up":'',"corner-up-left":'',"corner-up-right":'',cpu:'',"credit-card":'',crop:'',crosshair:'',database:'',delete:'',disc:'',"divide-circle":'',"divide-square":'',divide:'',"dollar-sign":'',"download-cloud":'',download:'',dribbble:'',droplet:'',"edit-2":'',"edit-3":'',edit:'',"external-link":'',"eye-off":'',eye:'',facebook:'',"fast-forward":'',feather:'',figma:'',"file-minus":'',"file-plus":'',"file-text":'',file:'',film:'',filter:'',flag:'',"folder-minus":'',"folder-plus":'',folder:'',framer:'',frown:'',gift:'',"git-branch":'',"git-commit":'',"git-merge":'',"git-pull-request":'',github:'',gitlab:'',globe:'',grid:'',"hard-drive":'',hash:'',headphones:'',heart:'',"help-circle":'',hexagon:'',home:'',image:'',inbox:'',info:'',instagram:'',italic:'',key:'',layers:'',layout:'',"life-buoy":'',"link-2":'',link:'',linkedin:'',list:'',loader:'',lock:'',"log-in":'',"log-out":'',mail:'',"map-pin":'',map:'',"maximize-2":'',maximize:'',meh:'',menu:'',"message-circle":'',"message-square":'',"mic-off":'',mic:'',"minimize-2":'',minimize:'',"minus-circle":'',"minus-square":'',minus:'',monitor:'',moon:'',"more-horizontal":'',"more-vertical":'',"mouse-pointer":'',move:'',music:'',"navigation-2":'',navigation:'',octagon:'',package:'',paperclip:'',"pause-circle":'',pause:'',"pen-tool":'',percent:'',"phone-call":'',"phone-forwarded":'',"phone-incoming":'',"phone-missed":'',"phone-off":'',"phone-outgoing":'',phone:'',"pie-chart":'',"play-circle":'',play:'',"plus-circle":'',"plus-square":'',plus:'',pocket:'',power:'',printer:'',radio:'',"refresh-ccw":'',"refresh-cw":'',repeat:'',rewind:'',"rotate-ccw":'',"rotate-cw":'',rss:'',save:'',scissors:'',search:'',send:'',server:'',settings:'',"share-2":'',share:'',"shield-off":'',shield:'',"shopping-bag":'',"shopping-cart":'',shuffle:'',sidebar:'',"skip-back":'',"skip-forward":'',slack:'',slash:'',sliders:'',smartphone:'',smile:'',speaker:'',square:'',star:'',"stop-circle":'',sun:'',sunrise:'',sunset:'',tablet:'',tag:'',target:'',terminal:'',thermometer:'',"thumbs-down":'',"thumbs-up":'',"toggle-left":'',"toggle-right":'',tool:'',"trash-2":'',trash:'',trello:'',"trending-down":'',"trending-up":'',triangle:'',truck:'',tv:'',twitch:'',twitter:'',type:'',umbrella:'',underline:'',unlock:'',"upload-cloud":'',upload:'',"user-check":'',"user-minus":'',"user-plus":'',"user-x":'',user:'',users:'',"video-off":'',video:'',voicemail:'',"volume-1":'',"volume-2":'',"volume-x":'',volume:'',watch:'',"wifi-off":'',wifi:'',wind:'',"x-circle":'',"x-octagon":'',"x-square":'',x:'',youtube:'',"zap-off":'',zap:'',"zoom-in":'',"zoom-out":''}},function(e){e.exports={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=Object.assign||function(e){for(var n=1;n2&&void 0!==arguments[2]?arguments[2]:[];!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e),this.name=n,this.contents=i,this.tags=l,this.attrs=t({},o.default,{class:"feather feather-"+n})}return l(e,[{key:"toSvg",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return""+this.contents+""}},{key:"toString",value:function(){return this.contents}}]),e}();n.default=c},function(e,n,i){"use strict";var t=o(i(12)),l=o(i(39)),r=o(i(38));function o(e){return e&&e.__esModule?e:{default:e}}e.exports={icons:t.default,toSvg:l.default,replace:r.default}},function(e,n,i){e.exports=i(0)},function(e,n,i){var t=i(2)("iterator"),l=!1;try{var r=0,o={next:function(){return{done:!!r++}},return:function(){l=!0}};o[t]=function(){return this},Array.from(o,function(){throw 2})}catch(e){}e.exports=function(e,n){if(!n&&!l)return!1;var i=!1;try{var r={};r[t]=function(){return{next:function(){return{done:i=!0}}}},e(r)}catch(e){}return i}},function(e,n,i){var t=i(30),l=i(2)("toStringTag"),r="Arguments"==t(function(){return arguments}());e.exports=function(e){var n,i,o;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(i=function(e,n){try{return e[n]}catch(e){}}(n=Object(e),l))?i:r?t(n):"Object"==(o=t(n))&&"function"==typeof n.callee?"Arguments":o}},function(e,n,i){var t=i(47),l=i(9),r=i(2)("iterator");e.exports=function(e){if(void 0!=e)return e[r]||e["@@iterator"]||l[t(e)]}},function(e,n,i){"use strict";var t=i(18),l=i(7),r=i(10);e.exports=function(e,n,i){var o=t(n);o in e?l.f(e,o,r(0,i)):e[o]=i}},function(e,n,i){var t=i(2),l=i(9),r=t("iterator"),o=Array.prototype;e.exports=function(e){return void 0!==e&&(l.Array===e||o[r]===e)}},function(e,n,i){var t=i(3);e.exports=function(e,n,i,l){try{return l?n(t(i)[0],i[1]):n(i)}catch(n){var r=e.return;throw void 0!==r&&t(r.call(e)),n}}},function(e,n){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,n,i){var t=i(52);e.exports=function(e,n,i){if(t(e),void 0===n)return e;switch(i){case 0:return function(){return e.call(n)};case 1:return function(i){return e.call(n,i)};case 2:return function(i,t){return e.call(n,i,t)};case 3:return function(i,t,l){return e.call(n,i,t,l)}}return function(){return e.apply(n,arguments)}}},function(e,n,i){"use strict";var t=i(53),l=i(24),r=i(51),o=i(50),a=i(27),c=i(49),p=i(48);e.exports=function(e){var n,i,y,h,x=l(e),s="function"==typeof this?this:Array,u=arguments.length,d=u>1?arguments[1]:void 0,f=void 0!==d,g=0,v=p(x);if(f&&(d=t(d,u>2?arguments[2]:void 0,2)),void 0==v||s==Array&&o(v))for(i=new s(n=a(x.length));n>g;g++)c(i,g,f?d(x[g],g):x[g]);else for(h=v.call(x),i=new s;!(y=h.next()).done;g++)c(i,g,f?r(h,d,[y.value,g],!0):y.value);return i.length=g,i}},function(e,n,i){var t=i(32),l=i(54);t({target:"Array",stat:!0,forced:!i(46)(function(e){Array.from(e)})},{from:l})},function(e,n,i){var t=i(6),l=i(3);e.exports=function(e,n){if(l(e),!t(n)&&null!==n)throw TypeError("Can't set "+String(n)+" as a prototype")}},function(e,n,i){var t=i(56);e.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var e,n=!1,i={};try{(e=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(i,[]),n=i instanceof Array}catch(e){}return function(i,l){return t(i,l),n?e.call(i,l):i.__proto__=l,i}}():void 0)},function(e,n,i){var t=i(0).document;e.exports=t&&t.documentElement},function(e,n,i){var t=i(28),l=i(13);e.exports=Object.keys||function(e){return t(e,l)}},function(e,n,i){var t=i(8),l=i(7),r=i(3),o=i(59);e.exports=t?Object.defineProperties:function(e,n){r(e);for(var i,t=o(n),a=t.length,c=0;a>c;)l.f(e,i=t[c++],n[i]);return e}},function(e,n,i){var t=i(3),l=i(60),r=i(13),o=i(15),a=i(58),c=i(34),p=i(16)("IE_PROTO"),y=function(){},h=function(){var e,n=c("iframe"),i=r.length;for(n.style.display="none",a.appendChild(n),n.src=String("javascript:"),(e=n.contentWindow.document).open(),e.write(" + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/posts/index.xml b/public/posts/index.xml new file mode 100644 index 0000000..b81860f --- /dev/null +++ b/public/posts/index.xml @@ -0,0 +1,32 @@ + + + + Posts on Basit's Blog + https://blog.rjbasitali.com/posts/ + Recent content in Posts on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + diff --git a/public/posts/page/1/index.html b/public/posts/page/1/index.html new file mode 100644 index 0000000..8b143f8 --- /dev/null +++ b/public/posts/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/posts/ + + + + + + diff --git a/public/posts/writing-a-golang-middleware-for-your-http-handler/index.html b/public/posts/writing-a-golang-middleware-for-your-http-handler/index.html new file mode 100644 index 0000000..e20b060 --- /dev/null +++ b/public/posts/writing-a-golang-middleware-for-your-http-handler/index.html @@ -0,0 +1,454 @@ + + + + + + + + + + + + Writing a Middleware for your HTTP handler – Golang | Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + + + + + +
+ + +
+ +
+ +
+
+ + +
+
+

+ Writing a Middleware for your HTTP handler – Golang +

+
+ + + + +
+ + + 4 minute read +
+ + + + + +
+
+ + + +
+

If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler.

+

You can achieve the following behaviour by writing a middleware, also known as a filter in some other backend frameworks. You can have as many middlewares as you want, each with a separate responsibility, and can chain them together to funnel incoming HTTP requests.

+

Writing a middleware in Go is pretty simple, you just need to wrap your middleware around the base HTTP handler, which so to speak is a thin wrapper around your HTTP handler.

+

Lets start with http package’s ListenAndServe method, which listens for incoming connections and serves with the handler to handle the requests, and lets write a handler for root "/" path which checks for the header Content-Type to see if it’s application/json, because our API only accepts JSON, and respond with following json {"msg":"Hello world!"} to any incoming request:

+
 1    func main() {
+ 2        mux := http.NewServeMux()
+ 3        mux.HandleFunc("/", rootHandler)
+ 4        http.ListenAndServe(":8080", mux)
+ 5    }
+ 6
+ 7    func rootHandler(w http.ResponseWriter, r *http.Request) {
+ 8        if r.Header.Get("Content-Type") != "application/json" {
+ 9                http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType)
+10                return
+11            }
+12        w.Write([]byte(`{"msg":"Hello world!"}`))
+13    }
+

Of course in reality you could have a dozen of handlers each with a different endpoint, but lets keep it simple for this tutorial.

+

Now let’s assume we have a dozen request handlers in our project and we want each handler to check for Content-Type header as we did in our rootHandler, we want our code to be DRY (Don’t Repeat Yourself).

+

Which brings us to writing a middleware to check the Content-Type header for each incoming request. Lets write a middleware and call it wrap:

+
1    func wrap(next http.Handler) http.Handler {
+2        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+3            // middleware logic
+4            next.ServeHTTP(w, r)
+5        })
+6    }
+

The wrap function takes in a Handler and returns a Handler, this syntax allows it to be used where we would normally use a request handler, and also allow us to chain multiple middlewares together. Now we can do something like wrap(handler) instead of just using handler, this would call our middleware logic before calling next.ServeHTTP(w, r) which can be the next middleware in the chain or a final call to our request handler.

+

In the following example, we are wrapping our wrap middleware around mux so every incoming request will pass through our middleware first:

+
 1    func main() {
+ 2        mux := http.NewServeMux()
+ 3        mux.HandleFunc("/", rootHandler)
+ 4        http.ListenAndServe(":8080", wrap(mux))
+ 5    }
+ 6
+ 7    func rootHandler(w http.ResponseWriter, r *http.Request) {
+ 8        w.Write([]byte(`{"msg":"Hello world!"}`))
+ 9    }
+10
+11    func wrap(next http.Handler) http.Handler {
+12        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+13            if r.Header.Get("Content-Type") != "application/json" {
+14                http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType)
+15                return
+16            }
+17            next.ServeHTTP(w, r)
+18        })
+19    }
+

So far we’ve been using a single middleware, lets see multiple middlewares chained together in action. We can define multiple middlewares with the same signature as of wrap, replacing the comment // middleware logic with our code.

+
+
1   func wrap(next http.Handler) http.Handler {
+2       return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+3           // middleware logic
+4           next.ServeHTTP(w, r)
+5       })
+6   }
+
+

Lets rename wrap to enforceJSON, and write another middleware which will log every incoming request’s method and path, and chain them both together:

+
 1    func main() {
+ 2        mux := http.NewServeMux()
+ 3        mux.HandleFunc("/", rootHandler)
+ 4        http.ListenAndServe(":8080", logRequest(enforceJSON(mux)))
+ 5    }
+ 6
+ 7    func rootHandler(w ResponseWriter, r *Request) {
+ 8        w.Write([]byte(`{"msg":"Hello world!"}`))
+ 9    }
+10
+11    func logRequest(next http.Handler) http.Handler {
+12        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+13            fmt.Println(r.Method, r.URL.Path)   // logs: GET /v1/users/1234
+14            next.ServeHTTP(w, r)
+15        })
+16    }
+17
+18    func enforceJSON(next http.Handler) http.Handler {
+19        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+20            if r.Header.Get("Content-Type") != "application/json" {
+21                http.Error(w, "Only application/json content type supported", http.StatusUnsupportedMediaType)
+22                return
+23            }
+24            next.ServeHTTP(w, r)
+25        })
+26    }
+

See how we are using logRequest(enforceJSON(mux)) instead of wrap(mux)? Now every incoming HTTP request will be logged and then checked for Content-Type before being passed onto the handler.

+

A cleaner way to chain multiple handlers is writing a single wrap middleware and chain all the middlewares inside wrap:

+
1    func wrap(handler http.Handler) http.Handler {
+2        handler = enforceJSON(handler)
+3        handler = logRequest(handler)
+4        return handler
+5    }
+

And then instead of:

+
1    http.ListenAndServe(":8080", logRequest(enforceJSON(mux)))
+

We can use:

+
1    http.ListenAndServe(":8080", wrap(mux))
+

+

That’s all on middlewares in golang today. Hope it was useful with your understanding on middlewares or how to write them.

+ +
+
+ + + + + + + + + +
+
+ + + + + + + + + + + +
+
+ + +
+ + +
+ + +
+ + + + + + + + + + + + diff --git a/public/posts/writing-your-own-reverse-proxy-using-golang/index.html b/public/posts/writing-your-own-reverse-proxy-using-golang/index.html new file mode 100644 index 0000000..d021f09 --- /dev/null +++ b/public/posts/writing-your-own-reverse-proxy-using-golang/index.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + Writing your own Reverse Proxy server using Golang | Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + + + + + +
+ + + + +
+
+ + +
+
+

+ Writing your own Reverse Proxy server using Golang +

+
+ + + + +
+ + + 5 minute read +
+ + + + + +
+
+ + + +
+

Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice.

+

Let us first start with defining Reverse Proxy and its common uses.

+

Reverse Proxy

+

A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. It is commonly used for:

+
    +
  • +

    Load Balancing – It can distribute the load across multiple available backend servers in such manner that maximizes speed and capacity utilization while ensuring no one server is overloaded, which can degrade performance.

    +
  • +
  • +

    Security – By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks.

    +
  • +
  • +

    Caching – It can cache content to serve, and you can deploy regional proxies to cache content related to specific regions.

    +
  • +
  • +

    TLS Termination – We can use the reverse proxy to terminate the SSL/TLS connection with the clients in cases where backend servers are being hosted on the same secure VPC network, and it’s ok to let the reverse proxy <-> backend server connection insecure.

    +
  • +
  • +

    More – Literally, there are a lot more use cases that can take leverage of reverse proxies, that I leave for you to explore.

    +
  • +
+

Personal Use Cases

+

Some common use cases I personally use reverse proxy server for are:

+
    +
  • +

    TLS Termination – Lets say I have multiple servers running on the same VPC network, each has it’s own copy of the TLS certificate issued to same domain name, it makes sense to let the reverse proxy handle the TLS handshake and terminate the secure connection and forward it insecurely to appropriate backend server on the same VPC isolated from public reach, now instead of having TLS certs on every backend server you can have them on proxy only.

    +
  • +
  • +

    Single VPS Dev Environment – I have multiple backend servers for a single project, each with separate responsibilities, that I need to deploy but the servers would sit ideal 99% of the time I don’t want to spin up multiple VPS for each for a dev environment, which would cost me money, also I don’t want to explicitly mention the port numbers on the client side to have the servers run on the same VPS. To solve this, I can run all the backend servers and reverse proxy on a single VPS, and have the requests proxied to servers running on different ports.

    +
  • +
+

Also sometimes for Authorization, Caching or implementing a feature like Request Limit per client.

+

Let’s Code

+

Enough with the uses, lets jump over to implementation. You are probably already familiar with Go standard library’s net/http package, there’s also a utility package for it you might have or might not have used, that is net/http/httputil. We’ll be using this utility package because it has the type ReverseProxy defined which makes writing a reverse proxy so simple using Go.

+

Conditions

+

Let’s define some condition based on which we’ll be forwarding the requests to appropriate server. For this tutorial lets stick to those conditions being the domain name or host of the requests:

+
    +
  1. If request came on host sub1.xyz.com, forward to localhost:8080.
  2. +
  3. If request came on host sub2.xyz.com, forward to localhost:8181.
  4. +
  5. If request came from an unknown host, forward to localhost:8888.
  6. +
+

main.go

+

Now lets create a main.go file, which will do the following:

+
 1    package main
+ 2
+ 3    import "net/http"
+ 4
+ 5    func main() {
+ 6        http.HandleFunc("/", proxy)
+ 7        if err := http.ListenAndServe(":4433", nil); err != nil {
+ 8            panic(err)
+ 9        }
+10    }
+11
+12    func proxy(w http.ResponseWriter, r *http.Request) {
+13        // We will get to this later ...
+14    }
+

Now that we have a basic server in place, let’s write our conditions for reverse proxy and use it to forward requests inside our proxy handler.

+
 1    package main
+ 2
+ 3    import (
+ 4        "net/http"
+ 5        "net/http/httputil"
+ 6        "net/url"
+ 7        "strings"
+ 8    )
+ 9
+10    func main() {
+11        http.HandleFunc("/", proxy)
+12        if err := http.ListenAndServe(":4433", nil); err != nil {
+13            panic(err)
+14        }
+15    }
+16
+17    func proxy(w http.ResponseWriter, r *http.Request) {
+18        if strings.HasSuffix(r.Host, "://sub1.xyz.com") { // forward requests from sub1.xyz.com to localhost:8080
+19            if url, err := url.Parse("http://localhost:8080"); err == nil {
+20                proxy := httputil.NewSingleHostReverseProxy(url)
+21                proxy.ServeHTTP(w, r)
+22            }
+23        } else if strings.HasSuffix(r.Host, "://sub2.xyz.com") { // forward requests from sub2.xyz.com to localhost:8181
+24            if url, err := url.Parse("http://localhost:8181"); err == nil {
+25                proxy := httputil.NewSingleHostReverseProxy(url)
+26                proxy.ServeHTTP(w, r)
+27            }
+28        } else { // forward requests from unknown host to localhost:8888
+29            if url, err := url.Parse("http://localhost:8888"); err == nil {
+30                proxy := httputil.NewSingleHostReverseProxy(url)
+31                proxy.ServeHTTP(w, r)
+32            }
+33        }
+34    }
+

The httputil’s NewSingleHostReverseProxy(url) function returns a new ReverseProxy that routes requests to url provided. And that’s all, or what minimal we need to run a reverse proxy based on conditions we defined.

+

But there are many ways we can refactor this code, starting from using predefined proxy objects instead of creating a new one on each request. Or I prefer a map map[string]*httputil.ReverseProxy which maps hosts to proxies, so we can use the map to check if a proxy exists for host then use it, else use the default one. I’ll leave the refactoring to anyone following this tutorial to keep it short.

+

Next Steps

+

Though it is pretty simple to write a reverse proxy using Go’s standard library, but it’s missing a lot of good stuff that comes with nginx or other solutions available. So you can start by implementing some of them into your own reverse proxy that is if the available solutions aren’t feasible and you are having to develop your own, like:

+
    +
  • Caching
  • +
  • Logging
  • +
  • Protocol Support (HTTP, HTTPS, HTTP/1.1, HTTP/2, …)
  • +
  • Rate Limit
  • +
  • TLS Support
  • +
  • Load Balancing
  • +
  • +
+ +
+
+ + + + + + + + + +
+
+ + + + + + + + + + + +
+
+ + +
+ + +
+ + +
+ + + + + + + + + + + + diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..cf4b646 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,49 @@ + + + + https://blog.rjbasitali.com/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/go/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/golang/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/posts/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/proxy/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/reverse-proxy/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + 2021-10-12T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/handler/ + 2021-08-01T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/http/ + 2021-08-01T22:05:04+05:00 + + https://blog.rjbasitali.com/tags/middleware/ + 2021-08-01T22:05:04+05:00 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + 2021-08-01T22:05:04+05:00 + + https://blog.rjbasitali.com/contact/ + 2021-08-01T16:26:01+05:00 + + https://blog.rjbasitali.com/about/ + 2021-07-31T22:39:25+05:00 + + https://blog.rjbasitali.com/categories/ + + diff --git a/public/tags/go/index.html b/public/tags/go/index.html new file mode 100644 index 0000000..cab47ea --- /dev/null +++ b/public/tags/go/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/go/index.xml b/public/tags/go/index.xml new file mode 100644 index 0000000..d3f99fd --- /dev/null +++ b/public/tags/go/index.xml @@ -0,0 +1,23 @@ + + + + go on Basit's Blog + https://blog.rjbasitali.com/tags/go/ + Recent content in go on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + diff --git a/public/tags/go/page/1/index.html b/public/tags/go/page/1/index.html new file mode 100644 index 0000000..efa84c2 --- /dev/null +++ b/public/tags/go/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/go/ + + + + + + diff --git a/public/tags/golang/index.html b/public/tags/golang/index.html new file mode 100644 index 0000000..d1bff37 --- /dev/null +++ b/public/tags/golang/index.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/golang/index.xml b/public/tags/golang/index.xml new file mode 100644 index 0000000..2b10b51 --- /dev/null +++ b/public/tags/golang/index.xml @@ -0,0 +1,32 @@ + + + + golang on Basit's Blog + https://blog.rjbasitali.com/tags/golang/ + Recent content in golang on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + diff --git a/public/tags/golang/page/1/index.html b/public/tags/golang/page/1/index.html new file mode 100644 index 0000000..54e8190 --- /dev/null +++ b/public/tags/golang/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/golang/ + + + + + + diff --git a/public/tags/handler/index.html b/public/tags/handler/index.html new file mode 100644 index 0000000..901bee0 --- /dev/null +++ b/public/tags/handler/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/handler/index.xml b/public/tags/handler/index.xml new file mode 100644 index 0000000..456faad --- /dev/null +++ b/public/tags/handler/index.xml @@ -0,0 +1,21 @@ + + + + handler on Basit's Blog + https://blog.rjbasitali.com/tags/handler/ + Recent content in handler on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Sun, 01 Aug 2021 22:05:04 +0500 + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + diff --git a/public/tags/handler/page/1/index.html b/public/tags/handler/page/1/index.html new file mode 100644 index 0000000..bc1c57a --- /dev/null +++ b/public/tags/handler/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/handler/ + + + + + + diff --git a/public/tags/http/index.html b/public/tags/http/index.html new file mode 100644 index 0000000..0ca6f66 --- /dev/null +++ b/public/tags/http/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/http/index.xml b/public/tags/http/index.xml new file mode 100644 index 0000000..a9d4b86 --- /dev/null +++ b/public/tags/http/index.xml @@ -0,0 +1,21 @@ + + + + http on Basit's Blog + https://blog.rjbasitali.com/tags/http/ + Recent content in http on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Sun, 01 Aug 2021 22:05:04 +0500 + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + diff --git a/public/tags/http/page/1/index.html b/public/tags/http/page/1/index.html new file mode 100644 index 0000000..fb99379 --- /dev/null +++ b/public/tags/http/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/http/ + + + + + + diff --git a/public/tags/index.html b/public/tags/index.html new file mode 100644 index 0000000..43cb9dc --- /dev/null +++ b/public/tags/index.html @@ -0,0 +1,141 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/index.xml b/public/tags/index.xml new file mode 100644 index 0000000..1acbaba --- /dev/null +++ b/public/tags/index.xml @@ -0,0 +1,75 @@ + + + + Tags on Basit's Blog + https://blog.rjbasitali.com/tags/ + Recent content in Tags on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + go + https://blog.rjbasitali.com/tags/go/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/go/ + + + + + golang + https://blog.rjbasitali.com/tags/golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/golang/ + + + + + proxy + https://blog.rjbasitali.com/tags/proxy/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/proxy/ + + + + + reverse-proxy + https://blog.rjbasitali.com/tags/reverse-proxy/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/reverse-proxy/ + + + + + handler + https://blog.rjbasitali.com/tags/handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/handler/ + + + + + http + https://blog.rjbasitali.com/tags/http/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/http/ + + + + + middleware + https://blog.rjbasitali.com/tags/middleware/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/tags/middleware/ + + + + + diff --git a/public/tags/middleware/index.html b/public/tags/middleware/index.html new file mode 100644 index 0000000..6a1a54e --- /dev/null +++ b/public/tags/middleware/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/middleware/index.xml b/public/tags/middleware/index.xml new file mode 100644 index 0000000..4809def --- /dev/null +++ b/public/tags/middleware/index.xml @@ -0,0 +1,21 @@ + + + + middleware on Basit's Blog + https://blog.rjbasitali.com/tags/middleware/ + Recent content in middleware on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Sun, 01 Aug 2021 22:05:04 +0500 + + Writing a Middleware for your HTTP handler – Golang + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + Sun, 01 Aug 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-a-golang-middleware-for-your-http-handler/ + If you are a backend developer working daily with HTTP requests then you have most likely already encountered situations where you want a common functionality across all the incoming HTTP requests, which can be as simple as checking if the Content-Type header only has the value application/json if you only support json, or maybe you want to spoof your HTTP request to change the method type from POST,GET or PUT to something else based on the X-HTTP-Method-Override header, or of course authenticate before finally passing the request to the destination HTTP handler. + + + + diff --git a/public/tags/middleware/page/1/index.html b/public/tags/middleware/page/1/index.html new file mode 100644 index 0000000..34d558d --- /dev/null +++ b/public/tags/middleware/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/middleware/ + + + + + + diff --git a/public/tags/proxy/index.html b/public/tags/proxy/index.html new file mode 100644 index 0000000..6fa4654 --- /dev/null +++ b/public/tags/proxy/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/proxy/index.xml b/public/tags/proxy/index.xml new file mode 100644 index 0000000..26e6784 --- /dev/null +++ b/public/tags/proxy/index.xml @@ -0,0 +1,23 @@ + + + + proxy on Basit's Blog + https://blog.rjbasitali.com/tags/proxy/ + Recent content in proxy on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + diff --git a/public/tags/proxy/page/1/index.html b/public/tags/proxy/page/1/index.html new file mode 100644 index 0000000..d6b0923 --- /dev/null +++ b/public/tags/proxy/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/proxy/ + + + + + + diff --git a/public/tags/reverse-proxy/index.html b/public/tags/reverse-proxy/index.html new file mode 100644 index 0000000..1d828ab --- /dev/null +++ b/public/tags/reverse-proxy/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Basit's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + +
+ + +
+ + + + + + diff --git a/public/tags/reverse-proxy/index.xml b/public/tags/reverse-proxy/index.xml new file mode 100644 index 0000000..50ded3d --- /dev/null +++ b/public/tags/reverse-proxy/index.xml @@ -0,0 +1,23 @@ + + + + reverse-proxy on Basit's Blog + https://blog.rjbasitali.com/tags/reverse-proxy/ + Recent content in reverse-proxy on Basit's Blog + Hugo -- gohugo.io + en-us + Basit Ali + Tue, 12 Oct 2021 22:05:04 +0500 + + Writing your own Reverse Proxy server using Golang + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Tue, 12 Oct 2021 22:05:04 +0500 + + https://blog.rjbasitali.com/posts/writing-your-own-reverse-proxy-using-golang/ + Writing a Reverse Proxy server in Go is a matter of single digit lines of code due to its rock solid standard library and its low level network plumbing capabilities. Recently I came across some use cases where I needed to write my own Reverse Proxy server and of course Go was the pragmatic choice. +Let us first start with defining Reverse Proxy and its common uses. +Reverse Proxy A Reverse Proxy is an intermediary server that sits between multiple clients and servers, and directs client requests to appropriate backend server. + + + + diff --git a/public/tags/reverse-proxy/page/1/index.html b/public/tags/reverse-proxy/page/1/index.html new file mode 100644 index 0000000..7030047 --- /dev/null +++ b/public/tags/reverse-proxy/page/1/index.html @@ -0,0 +1,10 @@ + + + + https://blog.rjbasitali.com/tags/reverse-proxy/ + + + + + + diff --git a/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.content b/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.content new file mode 100644 index 0000000..2324144 --- /dev/null +++ b/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.content @@ -0,0 +1,3 @@ +.inline{display:inline}.block{display:block}.inline-block{display:inline-block}.table{display:table}.table-cell{display:table-cell}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.left{float:left}.right{float:right}.fit{max-width:100%}.truncate{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.max-width-1{max-width:24rem}.max-width-2{max-width:32rem}.max-width-3{max-width:48rem}.max-width-4{max-width:64rem}.border-box{box-sizing:border-box}.m0{margin:0}.mt0{margin-top:0}.mr0{margin-right:0}.mb0{margin-bottom:0}.ml0{margin-left:0}.mx0{margin-right:0;margin-left:0}.my0{margin-top:0;margin-bottom:0}.m1{margin:.5rem}.mt1{margin-top:.5rem}.mr1{margin-right:.5rem}.mb1{margin-bottom:.5rem}.ml1{margin-left:.5rem}.mx1{margin-right:.5rem;margin-left:.5rem}.my1{margin-top:.5rem;margin-bottom:.5rem}.m2{margin:1rem}.mt2{margin-top:1rem}.mr2{margin-right:1rem}.mb2{margin-bottom:1rem}.ml2{margin-left:1rem}.mx2{margin-right:1rem;margin-left:1rem}.my2{margin-top:1rem;margin-bottom:1rem}.m3{margin:2rem}.mt3{margin-top:2rem}.mr3{margin-right:2rem}.mb3{margin-bottom:2rem}.ml3{margin-left:2rem}.mx3{margin-right:2rem;margin-left:2rem}.my3{margin-top:2rem;margin-bottom:2rem}.m4{margin:4rem}.mt4{margin-top:4rem}.mr4{margin-right:4rem}.mb4{margin-bottom:4rem}.ml4{margin-left:4rem}.mx4{margin-right:4rem;margin-left:4rem}.my4{margin-top:4rem;margin-bottom:4rem}.mxn1{margin-right:-.5rem;margin-left:-.5rem}.mxn2{margin-right:-1rem;margin-left:-1rem}.mxn3{margin-right:-2rem;margin-left:-2rem}.mxn4{margin-right:-4rem;margin-left:-4rem}.ml-auto{margin-left:auto}.mr-auto{margin-right:auto}.mx-auto{margin-right:auto;margin-left:auto}.p0{padding:0}.pt0{padding-top:0}.pr0{padding-right:0}.pb0{padding-bottom:0}.pl0{padding-left:0}.px0{padding-right:0;padding-left:0}.py0{padding-top:0;padding-bottom:0}.p1{padding:.5rem}.pt1{padding-top:.5rem}.pr1{padding-right:.5rem}.pb1{padding-bottom:.5rem}.pl1{padding-left:.5rem}.py1{padding-top:.5rem;padding-bottom:.5rem}.px1{padding-right:.5rem;padding-left:.5rem}.p2{padding:1rem}.pt2{padding-top:1rem}.pr2{padding-right:1rem}.pb2{padding-bottom:1rem}.pl2{padding-left:1rem}.py2{padding-top:1rem;padding-bottom:1rem}.px2{padding-right:1rem;padding-left:1rem}.p3{padding:2rem}.pt3{padding-top:2rem}.pr3{padding-right:2rem}.pb3{padding-bottom:2rem}.pl3{padding-left:2rem}.py3{padding-top:2rem;padding-bottom:2rem}.px3{padding-right:2rem;padding-left:2rem}.p4{padding:4rem}.pt4{padding-top:4rem}.pr4{padding-right:4rem}.pb4{padding-bottom:4rem}.pl4{padding-left:4rem}.py4{padding-top:4rem;padding-bottom:4rem}.px4{padding-right:4rem;padding-left:4rem}h1,.h1{display:block;margin-top:3rem;margin-bottom:1rem;color:#2bbc8a;letter-spacing:.01em;font-weight:700;font-style:normal;font-size:1.5em;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h2,.h2{position:relative;display:block;margin-top:2rem;margin-bottom:.5rem;color:#383838;text-transform:none;letter-spacing:normal;font-weight:bold;font-size:1rem}h3{color:#383838;text-decoration:underline;font-weight:bold;font-size:.9rem}h4 h5 h6{display:inline;text-decoration:none;color:#8c8c8c;font-weight:bold;font-size:.9rem}h3 h4 h5 h6{margin-top:.9rem;margin-bottom:.5rem}hr{border:0.5px dashed #8c8c8c;opacity:.5;margin:0;margin-top:20px;margin-bottom:20px}strong{font-weight:bold}em cite{font-style:italic}sup sub{position:relative;vertical-align:baseline;font-size:.75em;line-height:0}sup{top:-.5em}sub{bottom:-.2em}small{font-size:.85em}acronym abbr{border-bottom:1px dotted}ul ol dl{line-height:1.725}ul ul,ol ul,ul ol,ol ol{margin-top:0;margin-bottom:0}ol{list-style:decimal}dt{font-weight:bold}table{width:100%;border-collapse:collapse;text-align:left;font-size:12px;overflow:auto;display:block}th{padding:8px;border-bottom:1px dashed #666;color:#383838;font-weight:bold;font-size:13px}td{padding:0 8px;border-bottom:none}@font-face{font-style:normal;font-family:"JetBrains Mono";font-display:swap;src:local("JetBrains Mono"),local("JetBrains-Mono"),url("../lib/JetBrainsMono/web/woff2/JetBrainsMono-Regular.woff2") format("woff2"),url("../lib/JetBrainsMono/web/woff/JetBrainsMono-Regular.woff") format("woff"),url("../lib/JetBrainsMono/web/eot/JetBrainsMono-Regular.eot") format("embedded-opentype"),url("../lib/JetBrainsMono/ttf/JetBrainsMono-Regular.ttf") format("truetype")}*,*:before,*:after{box-sizing:border-box}html{margin:0;padding:0;height:100%;border-top:2px solid #383838;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0;height:100%;background-color:#fff;color:#383838;font-display:swap;font-weight:400;font-size:14px;font-family:"JetBrains Mono",monospace;line-height:1.725;text-rendering:geometricPrecision;flex:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.content{position:relative;display:flex;flex-direction:column;min-height:100%;overflow-wrap:break-word}.content p{hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;-webkit-hyphens:auto}.content code{hyphens:manual;-moz-hyphens:manual;-ms-hyphens:manual;-webkit-hyphens:manual}.content a{color:#383838;text-decoration:none;background-image:linear-gradient(transparent, transparent 5px, #383838 5px, #383838);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.content a:hover{background-image:linear-gradient(transparent, transparent 4px, #d480aa 4px, #d480aa)}.content a.icon{background:none}.content a.icon:hover{color:#d480aa}.content h1 a,.content .h1 a,.content h2 a,.content h3 a,.content h4 a,.content h5 a,.content h6 a{background:none;color:inherit;text-decoration:none}.content h1 a:hover,.content .h1 a:hover,.content h2 a:hover,.content h3 a:hover,.content h4 a:hover,.content h5 a:hover,.content h6 a:hover{background-image:linear-gradient(transparent, transparent 6px, #d480aa 6px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.content h6 a{background:none;color:inherit;text-decoration:none}.content h6 a:hover{background-image:linear-gradient(transparent, transparent 6px, #d480aa 6px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}@media (min-width: 540px){.image-wrap{flex-direction:row;margin-bottom:2rem}.image-wrap .image-block{flex:1 0 35%;margin-right:2rem}.image-wrap p{flex:1 0 65%}}.max-width{max-width:48rem}@media (max-width: 480px){.px3{padding-right:1rem;padding-left:1rem}.my4{margin-top:2rem;margin-bottom:2rem}}@media (min-width: 480px){p{text-align:justify}}#header{margin:0 auto 2rem;width:100%}#header h1,#header .h1{margin-top:0;margin-bottom:0;color:#383838;letter-spacing:.01em;font-weight:700;font-style:normal;font-size:1.5rem;line-height:2rem;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}#header a{background:none;color:inherit;text-decoration:none}#header #logo{display:inline-block;float:left;margin-right:20px;width:50px;height:50px;border-radius:5px;background-size:50px 50px;background-repeat:no-repeat;filter:grayscale(100%);-webkit-filter:grayscale(100%)}#header #nav{color:#2bbc8a;letter-spacing:.01em;font-weight:200;font-style:normal;font-size:.8rem}#header #nav ul{margin:0;padding:0;list-style-type:none;line-height:15px}#header #nav ul a{margin-right:15px;color:#2bbc8a}#header #nav ul a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#header #nav ul li{display:inline-block;margin-right:15px;border-right:1px dotted;border-color:#2bbc8a;vertical-align:middle}#header #nav ul .icon{display:none}#header #nav ul li:last-child{margin-right:0;border-right:0}#header #nav ul li:last-child a{margin-right:0}#header:hover #logo{filter:none;-webkit-filter:none}@media screen and (max-width: 480px){#header #title{display:table;margin-right:5rem;min-height:50px}#header #title h1{display:table-cell;vertical-align:middle}#header #nav ul a:hover{background:none}#header #nav ul li{display:none;border-right:0}#header #nav ul li.icon{position:absolute;top:77px;right:1rem;display:inline-block}#header #nav ul.responsive li{display:block}#header #nav li:not(:first-child){padding-top:1rem;padding-left:70px;font-size:1rem}}#header-post{position:fixed;top:2rem;right:0;display:inline-block;float:right;z-index:100}#header-post a{background:none;color:inherit;text-decoration:none}#header-post a.icon{background:none}#header-post a.icon:hover{color:#d480aa}#header-post nav ul{display:block;list-style-image:none;list-style-position:outside;list-style-type:none;padding-inline-start:40px}#header-post nav ul li{display:list-item;margin-right:0px}#header-post nav>ul{margin-block-end:1em;margin-block-start:1em}#header-post ul{display:inline-block;margin:0;padding:0;list-style-type:none}#header-post ul li{display:inline-block;margin-right:15px;vertical-align:middle}#header-post ul li:last-child{margin-right:0}#header-post #menu-icon{float:right;margin-right:2rem;margin-left:15px}#header-post #menu-icon:hover{color:#2bbc8a}#header-post #menu-icon-tablet{float:right;margin-right:2rem;margin-left:15px}#header-post #menu-icon-tablet:hover{color:#2bbc8a}#header-post #top-icon-tablet{position:fixed;right:2rem;bottom:2rem;margin-right:2rem;margin-left:15px}#header-post #top-icon-tablet:hover{color:#2bbc8a}#header-post .active{color:#2bbc8a}#header-post #menu{visibility:hidden;margin-right:2rem}#header-post #nav{color:#2bbc8a;letter-spacing:.01em;font-weight:200;font-style:normal;font-size:.8rem}#header-post #nav ul{line-height:15px}#header-post #nav ul a{margin-right:15px;color:#2bbc8a}#header-post #nav ul a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#header-post #nav ul li{border-right:1px dotted #2bbc8a}#header-post #nav ul li:last-child{margin-right:0;border-right:0}#header-post #nav ul li:last-child a{margin-right:0}#header-post #actions{float:right;margin-top:2rem;margin-right:2rem;width:100%;text-align:right}#header-post #actions ul{display:block}#header-post #actions .info{display:block;font-style:italic}#header-post #share{clear:both;padding-top:1rem;padding-right:2rem;text-align:right}#header-post #share li{display:block;margin:0}#header-post #toc{float:right;clear:both;overflow:auto;margin-top:1rem;padding-right:2rem;max-width:20em;max-height:calc(95vh - 7rem);text-align:right}#header-post #toc a:hover{color:#d480aa}#header-post #toc nav>ul>li{color:#383838;font-size:.8rem}#header-post #toc nav>ul>li:before{color:#2bbc8a;content:"#";margin-right:8px}#header-post #toc nav>ul>li>ul>li{color:#666;font-size:.7rem}#header-post #toc nav>ul>li>ul>li:before{color:#2bbc8a;content:"·";font-weight:bold;margin-right:3px}#header-post #toc nav>ul>li>ul>li>ul>li{color:#333;font-size:.4rem}#header-post #toc .toc-level-5{display:none}#header-post #toc .toc-level-6{display:none}#header-post #toc .toc-number{display:none}@media screen and (max-width: 500px){#header-post{display:none}}@media screen and (max-width: 900px){#header-post #menu-icon{display:none}#header-post #actions{display:none}}@media screen and (max-width: 1199px){#header-post #toc{display:none}}@media screen and (min-width: 900px){#header-post #menu-icon-tablet{display:none !important}#header-post #top-icon-tablet{display:none !important}}@media screen and (min-width: 1199px){#header-post #actions{width:auto}#header-post #actions ul{display:inline-block;float:right}#header-post #actions .info{display:inline;float:left;margin-right:2rem;font-style:italic}}#footer-post{position:fixed;right:0;bottom:0;left:0;z-index:5000000;width:100%;border-top:1px solid #666;background:#fafafa;transition:opacity .2s}#footer-post a{background:none;color:inherit;text-decoration:none}#footer-post a.icon{background:none}#footer-post a.icon:hover{color:#d480aa}#footer-post #nav-footer{padding-right:1rem;padding-left:1rem;background:#e6e6e6;text-align:center}#footer-post #nav-footer a{color:#2bbc8a;font-size:1em}#footer-post #nav-footer a:hover{background-image:linear-gradient(transparent, transparent 5px, #2bbc8a 5px, #2bbc8a);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}#footer-post #nav-footer ul{display:table;margin:0;padding:0;width:100%;list-style-type:none}#footer-post #nav-footer ul li{display:inline-table;padding:10px;width:20%;vertical-align:middle}#footer-post #actions-footer{overflow:auto;margin-top:1rem;margin-bottom:1rem;padding-right:1rem;padding-left:1rem;width:100%;text-align:center;white-space:nowrap}#footer-post #actions-footer a{display:inline-block;padding-left:1rem;color:#2bbc8a}#footer-post #share-footer{padding-right:1rem;padding-left:1rem;background:#e6e6e6;text-align:center}#footer-post #share-footer ul{display:table;margin:0;padding:0;width:100%;list-style-type:none}#footer-post #share-footer ul li{display:inline-table;padding:10px;width:20%;vertical-align:middle}#footer-post #toc-footer{clear:both;padding-top:1rem;padding-bottom:1rem;background:#e6e6e6;text-align:left}#footer-post #toc-footer #TableOfContents ul{margin:0;padding-left:20px;list-style-type:none}#footer-post #toc-footer #TableOfContents ul li{line-height:30px}#footer-post #toc-footer a:hover{color:#d480aa}#footer-post #toc-footer #TableOfContents>ul>li{color:#383838;font-size:.8rem}#footer-post #toc-footer #TableOfContents>ul>li:before{color:#2bbc8a;content:"#";margin-right:8px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li{color:#666;font-size:.7rem;line-height:15px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li:before{color:#2bbc8a;content:"·";font-weight:bold;margin-right:3px}#footer-post #toc-footer #TableOfContents>ul>li>ul>li>ul>li{display:none}@media screen and (min-width: 500px){#footer-post-container{display:none}}.post-list{padding:0}.post-list .post-item{margin-bottom:1rem;margin-left:0;list-style-type:none}.post-list .post-item .meta{display:block;margin-right:16px;min-width:100px;color:#666;font-size:14px}@media (min-width: 480px){.post-list .post-item{display:flex;margin-bottom:5px}.post-list .post-item .meta{text-align:left}}.project-list{padding:0;list-style:none}.project-list .project-item{margin-bottom:5px}.project-list .project-item p{display:inline}article header .posttitle{margin-top:0;margin-bottom:0;text-transform:none;font-size:1.5em;line-height:1.25}article header .meta{margin-top:0;margin-bottom:1rem}article header .meta *{color:#8c8c8c;font-size:.85rem}article header .author{text-transform:uppercase;letter-spacing:.01em;font-weight:700}article header .postdate{display:inline}article .content h2:before{position:absolute;top:-4px;left:-1rem;color:#2bbc8a;content:"#";font-weight:bold;font-size:1.2rem}article .content img,article .content video{display:block;margin:auto;max-width:100%;height:auto}article .content img .video-container,article .content video .video-container{position:relative;overflow:hidden;padding-top:56.25% e;height:0}article .content img .video-container iframe,article .content img .video-container object,article .content img .video-container embed,article .content video .video-container iframe,article .content video .video-container object,article .content video .video-container embed{position:absolute;top:0;left:0;margin-top:0;width:100%;height:100%}article .content img blockquote,article .content video blockquote{margin:1rem 10px;padding:.5em 10px;background:inherit;color:#2bbc8a;quotes:"\201C" "\201D" "\2018" "\2019";font-weight:bold}article .content img blockquote p,article .content video blockquote p{margin:0}article .content img blockquote:before,article .content video blockquote:before{margin-right:.25em;color:#2bbc8a;content:"\201C";vertical-align:-.4em;font-size:2em;line-height:.1em}article .content img blockquote footer,article .content video blockquote footer{margin:line-height 0;color:#666;font-size:11px}article .content img blockquote footer a,article .content video blockquote footer a{background-image:linear-gradient(transparent, transparent 5px, #666 5px, #666);color:#666}article .content img blockquote footer a:hover,article .content video blockquote footer a:hover{background-image:linear-gradient(transparent, transparent 4px, #999 4px, #999);color:#999}article .content img blockquote footer cite:before,article .content video blockquote footer cite:before{padding:0 .5em;content:"—"}article .content img .pullquote,article .content video .pullquote{margin:0;width:45%;text-align:left}article .content img .pullquote.left,article .content video .pullquote.left{margin-right:1em;margin-left:.5em}article .content img .pullquote.right,article .content video .pullquote.right{margin-right:.5em;margin-left:1em}article .content img .caption,article .content video .caption{position:relative;display:block;margin-top:.5em;color:#666;text-align:center;font-size:.9em}.posttitle{text-transform:none;font-size:1.5em;line-height:1.25}.article-tag .tag-link:before{content:"#";background-image:linear-gradient(transparent, transparent 10px, #d480aa 10px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}.article-category .category-link{background-image:linear-gradient(transparent, transparent 10px, #d480aa 10px, #d480aa);background-position:bottom;background-size:100% 6px;background-repeat:repeat-x}@media (min-width: 480px){.article-read-time,.article-tag,.article-category{display:inline}.article-read-time:before,.article-tag:before,.article-category:before{content:"|"}}#archive .post-list{padding:0}#archive .post-list .post-item{margin-bottom:1rem;margin-left:0;list-style-type:none}#archive .post-list .post-item .meta{display:block;margin-right:16px;min-width:100px;color:#666;font-size:14px}@media (min-width: 480px){#archive .post-list .post-item{display:flex;margin-bottom:5px;margin-left:1rem}#archive .post-list .post-item .meta{text-align:left}}.blog-post-comments{margin-top:4rem}#footer{position:absolute;bottom:0;margin-bottom:10px;width:100%;color:#666;vertical-align:top;text-align:center;font-size:11px}#footer ul{margin:0;padding:0;list-style:none}#footer li{display:inline-block;margin-right:15px;border-right:1px solid;border-color:#666;vertical-align:middle}#footer li a{margin-right:15px}#footer li:last-child{margin-right:0;border-right:0}#footer li:last-child a{margin-right:0}#footer a{color:#666;text-decoration:underline;background-image:none}#footer a:hover{color:#999}#footer .footer-left{height:20px;vertical-align:middle;line-height:20px}@media (min-width: 39rem){#footer{display:flex;flex-flow:row wrap;justify-content:space-between;align-items:center;align-content:center;margin-bottom:20px}#footer .footer-left{align-self:flex-start;margin-right:20px}#footer .footer-right{align-self:flex-end}}.pagination{display:inline-block;margin-top:2rem;width:100%;text-align:center}.pagination .page-number{color:#383838;font-size:.8rem}.pagination a{padding:4px 6px;border-radius:5px;background-image:none;color:#383838;text-decoration:none}.pagination a:hover{background-image:none}.pagination a:hover:not(.active){color:#383838}.search-input{padding:4px 7px;width:100%;outline:none;border:solid 1px #8c8c8c;border-radius:5px;background-color:#fff;color:#383838;font-size:1.2rem;-webkit-border-radius:5px;-moz-border-radius:5px}.search-input:focus{border:solid 1px #2bbc8a}#search-result ul.search-result-list{padding:0;list-style-type:none}#search-result li{margin:2em auto}#search-result a.search-result-title{background-image:none;color:#383838;text-transform:capitalize;font-weight:bold;line-height:1.2}#search-result p.search-result{overflow:hidden;margin:.4em auto;max-height:13em;text-align:justify;font-size:.8em}#search-result em.search-keyword{border-bottom:1px dashed #d480aa;color:#d480aa;font-weight:bold}.search-no-result{display:none;padding-bottom:.5em;color:#383838}#tag-cloud .tag-cloud-title{color:#666}#tag-cloud .tag-cloud-tags{clear:both;text-align:center}#tag-cloud .tag-cloud-tags a{display:inline-block;margin:10px}.tooltipped{position:relative}.tooltipped::after{position:absolute;z-index:1000000;display:none;padding:.2em .5em;-webkit-font-smoothing:subpixel-antialiased;color:#fff;font-display:swap;font-weight:400;font-size:11.2px;font-family:"JetBrains Mono",monospace;line-height:1.725;text-rendering:geometricPrecision;text-align:center;word-wrap:break-word;white-space:pre;content:attr(aria-label);background:#383838;border-radius:3px;opacity:0}.tooltipped::before{position:absolute;z-index:1000001;display:none;width:0;height:0;color:#383838;pointer-events:none;content:'';border:6px solid transparent;opacity:0}@keyframes tooltip-appear{from{opacity:0}to{opacity:1}}.tooltipped:hover::before,.tooltipped:hover::after,.tooltipped:active::before,.tooltipped:active::after,.tooltipped:focus::before,.tooltipped:focus::after{display:inline-block;text-decoration:none;animation-name:tooltip-appear;animation-duration:0.1s;animation-fill-mode:forwards;animation-timing-function:ease-in}.tooltipped-s::after,.tooltipped-sw::after{top:100%;right:50%;margin-top:6px}.tooltipped-s::before,.tooltipped-sw::before{top:auto;right:50%;bottom:-7px;margin-right:-6px;border-bottom-color:#383838}.tooltipped-sw::after{margin-right:-16px}.tooltipped-s::after{transform:translateX(50%)}#categories .category-list-title{color:#666}#categories .category-list .category-list-item .category-list-count{color:#666}#categories .category-list .category-list-item .category-list-count:before{content:" ("}#categories .category-list .category-list-item .category-list-count:after{content:")"}pre{overflow-x:auto;padding:15px 15px 10px 15px;border:1px dotted #666;border-radius:2px;-webkit-border-radius:2px;font-size:13px;font-family:"JetBrains Mono",monospace;line-height:22px;position:relative}pre .code-copy-btn{position:absolute;top:0;right:0;border:0;border-radius:0 2px;padding:0;font-family:"JetBrains Mono", monospace;font-weight:800;font-size:0.9em;line-height:1.7;color:#fff;background-color:#8c8c8c;min-width:60px;text-align:center;cursor:pointer;letter-spacing:0em}pre .code-copy-btn:hover{background-color:#666;color:#2bbc8a}pre code{display:block;padding:0;border:none}code{font-family:"JetBrains Mono",monospace;padding:0 5px;border:1px dotted #666;border-radius:2px;-webkit-border-radius:2px}.highlight>div{border-radius:2px;-webkit-border-radius:2px}.highlight pre{border:none;background:none}.highlight table pre{margin-top:0}.highlight table td:first-child pre{padding-right:0}.highlight table td:last-child pre{padding-left:0} + +/*# sourceMappingURL=styles.css.map */ \ No newline at end of file diff --git a/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.json b/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.json new file mode 100644 index 0000000..acc1a4d --- /dev/null +++ b/resources/_gen/assets/scss/scss/style.scss_17a317b87063135b4df76ed814d78726.json @@ -0,0 +1 @@ +{"Target":"css/styles.94f653e9e151e28067a7c5dbbc4600cbd5a3c721e79faaf971e523c40f3b249b8e4f20bb57810dfffa8d559ca5c140fd56eb4cd9c0853113ad08e66afdb08bdd.css","MediaType":"text/css","Data":{"Integrity":"sha512-lPZT6eFR4oBnp8XbvEYAy9WjxyHnn6r5ceUjxA87JJuOTyC7V4EN//qNVZylwUD9VutM2cCFMROtCOZq/bCL3Q=="}} \ No newline at end of file diff --git a/themes/cactus b/themes/cactus new file mode 160000 index 0000000..a27a143 --- /dev/null +++ b/themes/cactus @@ -0,0 +1 @@ +Subproject commit a27a14348040b919818cbc862e3667c05f90b077