mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-12 06:24:10 +01:00
console: switch to Vue.JS + Tailwind CSS + Headless UI for the frontend
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,5 +2,5 @@
|
||||
/test/
|
||||
/inlet/flow/decoder/flow*.pb.go
|
||||
|
||||
/console/data/node_modules/
|
||||
/console/data/assets/generated/
|
||||
/console/frontend/node_modules/
|
||||
/console/data/frontend/
|
||||
|
||||
@@ -14,6 +14,11 @@ run tests:
|
||||
paths:
|
||||
- .go-cache/
|
||||
- bin/
|
||||
- key:
|
||||
files:
|
||||
- yarn.lock
|
||||
paths:
|
||||
- .yarn-cache
|
||||
variables:
|
||||
FF_NETWORK_PER_BUILD: "true"
|
||||
CI_AKVORADO_FUNCTIONAL_TESTS: "true"
|
||||
@@ -31,8 +36,9 @@ run tests:
|
||||
- name: clickhouse/clickhouse-server:22.2
|
||||
alias: clickhouse
|
||||
script:
|
||||
- export GOMODCACHE=$PWD/.go-cache
|
||||
- time apk add --no-cache git make gcc musl-dev protoc shared-mime-info yarn
|
||||
- export GOMODCACHE=$PWD/.go-cache
|
||||
- yarn config set cacheFolder $PWD/.yarn-cache
|
||||
- time go mod download
|
||||
- time make test
|
||||
- time make test-race || make test-race
|
||||
|
||||
18
Makefile
18
Makefile
@@ -13,7 +13,7 @@ M = $(shell if [ "$$(tput colors 2> /dev/null || echo 0)" -ge 8 ]; then printf "
|
||||
|
||||
export GO111MODULE=on
|
||||
|
||||
GENERATED = inlet/flow/decoder/flow-1.pb.go console/data/node_modules console/data/assets/generated
|
||||
GENERATED = inlet/flow/decoder/flow-1.pb.go console/data/frontend console/frontend/node_modules
|
||||
|
||||
.PHONY: all
|
||||
all: fmt lint $(GENERATED) | $(BIN) ; $(info $(M) building executable…) @ ## Build program binary
|
||||
@@ -50,14 +50,14 @@ $(BIN)/protoc-gen-go: PACKAGE=google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
inlet/flow/decoder/%.pb.go: inlet/flow/data/schemas/%.proto | $(PROTOC_GEN_GO) ; $(info $(M) compiling protocol buffers definition…)
|
||||
$Q $(PROTOC) -I=. --plugin=$(PROTOC_GEN_GO) --go_out=. --go_opt=module=$(MODULE) $<
|
||||
|
||||
console/data/node_modules: console/data/package.json console/data/yarn.lock ; $(info $(M) fetching node modules…)
|
||||
$Q yarn install --frozen-lockfile --cwd console/data && touch $@
|
||||
console/data/assets/generated: console/data/node_modules Makefile ; $(info $(M) copying static assets…)
|
||||
$Q rm -rf $@ && mkdir -p $@/stylesheets $@/javascript $@/fonts
|
||||
$Q cp console/data/node_modules/@mdi/font/fonts/materialdesignicons-webfont.woff* $@/fonts/.
|
||||
$Q cp console/data/node_modules/@mdi/font/css/materialdesignicons.min.css $@/stylesheets/.
|
||||
$Q cp console/data/node_modules/bootstrap/dist/css/bootstrap.min.css $@/stylesheets/.
|
||||
$Q cp console/data/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js $@/javascript/.
|
||||
console/frontend/node_modules: console/frontend/package.json console/frontend/yarn.lock
|
||||
console/frontend/node_modules: ; $(info $(M) fetching node modules…)
|
||||
$Q yarn install --frozen-lockfile --cwd console/frontend && touch $@
|
||||
console/data/frontend: Makefile console/frontend/node_modules
|
||||
console/data/frontend: console/frontend/index.html console/frontend/vite.config.js
|
||||
console/data/frontend: $(shell find console/frontend/src -type f)
|
||||
console/data/frontend: ; $(info $(M) building console frontend…)
|
||||
$Q cd console/frontend && yarn build
|
||||
|
||||
# These files are versioned in Git, but we may want to update them.
|
||||
clickhouse/data/protocols.csv:
|
||||
|
||||
@@ -76,8 +76,7 @@ func consoleStart(r *reporter.Reporter, config ConsoleConfiguration, checkOnly b
|
||||
return fmt.Errorf("unable to initialize HTTP component: %w", err)
|
||||
}
|
||||
consoleComponent, err := console.New(r, config.Console, console.Dependencies{
|
||||
Daemon: daemonComponent,
|
||||
HTTP: httpComponent,
|
||||
HTTP: httpComponent,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize console component: %w", err)
|
||||
|
||||
@@ -2,38 +2,32 @@ package console
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed data/assets/generated data/assets/images
|
||||
//go:embed data/frontend
|
||||
var embeddedAssets embed.FS
|
||||
|
||||
func (c *Component) assetsHandlerFunc(w http.ResponseWriter, req *http.Request) {
|
||||
assets := c.embedOrLiveFS(embeddedAssets, "data/assets")
|
||||
rpath := strings.TrimPrefix(req.URL.Path, "/assets/")
|
||||
rpath = strings.Trim(rpath, "/")
|
||||
|
||||
for _, p := range []string{
|
||||
fmt.Sprintf("%s", rpath),
|
||||
fmt.Sprintf("generated/%s", rpath),
|
||||
} {
|
||||
f, err := http.FS(assets).Open(p)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
st, err := f.Stat()
|
||||
if err != nil || st.IsDir() {
|
||||
continue
|
||||
}
|
||||
http.ServeContent(w, req, path.Base(rpath), st.ModTime(), f)
|
||||
f.Close()
|
||||
assets := c.embedOrLiveFS(embeddedAssets, "data/frontend")
|
||||
upath := req.URL.Path
|
||||
if !strings.HasPrefix(upath, "/") {
|
||||
upath = "/" + upath
|
||||
req.URL.Path = upath
|
||||
}
|
||||
// Serve assets using a file server
|
||||
if strings.HasPrefix(upath, "/assets/") {
|
||||
http.FileServer(http.FS(assets)).ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "Asset not found.", http.StatusNotFound)
|
||||
// Everything else is routed to index.html
|
||||
f, err := http.FS(assets).Open("index.html")
|
||||
if err != nil {
|
||||
http.Error(w, "Application not found.", http.StatusInternalServerError)
|
||||
}
|
||||
http.ServeContent(w, req, "index.html", time.Time{}, f)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
@@ -5,20 +5,28 @@ import (
|
||||
netHTTP "net/http"
|
||||
"testing"
|
||||
|
||||
"akvorado/common/daemon"
|
||||
"akvorado/common/http"
|
||||
"akvorado/common/reporter"
|
||||
)
|
||||
|
||||
func TestServeAssets(t *testing.T) {
|
||||
for _, live := range []bool{false, true} {
|
||||
for _, f := range []string{"images/akvorado.svg", "javascript/bootstrap.bundle.min.js"} {
|
||||
cases := []struct {
|
||||
Path string
|
||||
Code int
|
||||
}{
|
||||
{"", 200},
|
||||
{"something", 200},
|
||||
{"assets/akvorado.399701ee.svg", 200},
|
||||
{"assets/somethingelse.svg", 404},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
var name string
|
||||
switch live {
|
||||
case true:
|
||||
name = fmt.Sprintf("livefs-%s", f)
|
||||
name = fmt.Sprintf("livefs-%s", tc.Path)
|
||||
case false:
|
||||
name = fmt.Sprintf("embeddedfs-%s", f)
|
||||
name = fmt.Sprintf("embeddedfs-%s", tc.Path)
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
r := reporter.NewMock(t)
|
||||
@@ -26,20 +34,19 @@ func TestServeAssets(t *testing.T) {
|
||||
_, err := New(r, Configuration{
|
||||
ServeLiveFS: live,
|
||||
}, Dependencies{
|
||||
HTTP: h,
|
||||
Daemon: daemon.NewMock(t),
|
||||
HTTP: h,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error:\n%+v", err)
|
||||
}
|
||||
|
||||
resp, err := netHTTP.Get(fmt.Sprintf("http://%s/assets/%s", h.Address, f))
|
||||
resp, err := netHTTP.Get(fmt.Sprintf("http://%s/%s", h.Address, tc.Path))
|
||||
if err != nil {
|
||||
t.Fatalf("GET /assets/%s:\n%+v", f, err)
|
||||
t.Fatalf("GET /%s:\n%+v", tc.Path, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("GET /assets/%s: got status code %d, not 200", f, resp.StatusCode)
|
||||
if resp.StatusCode != tc.Code {
|
||||
t.Errorf("GET /%s: got status code %d, not %d", tc.Path, resp.StatusCode, tc.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 553 KiB |
@@ -1,10 +0,0 @@
|
||||
:root {
|
||||
--bs-primary: #008aff;
|
||||
--bs-primary-rgb: 0,138,255;
|
||||
--bs-secondary: #48092f;
|
||||
--bs-secondary-rgb: 72,9,47;
|
||||
}
|
||||
|
||||
.ak-navbar {
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
.ak-docs-markdown p > img {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.ak-docs-toc ul {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||

|
||||
|
||||
# Introduction
|
||||
|
||||
*Akvorado*[^name] is a flow collector, hydrater and exporter. It
|
||||
@@ -12,7 +10,7 @@ exports them to Kafka.
|
||||
|
||||
## Big picture
|
||||
|
||||

|
||||

|
||||
|
||||
*Akvorado* is split into three components:
|
||||
|
||||
|
||||
@@ -175,3 +175,16 @@ FROM flows
|
||||
|
||||
If the lag is too big, you need to increase the number of threads. See
|
||||
[ClickHouse configuration](02-configuration.md#clickhouse) for details.
|
||||
|
||||
Another way to achieve the same thing is to look at the consumer group
|
||||
from Kafka's point of view:
|
||||
|
||||
```console
|
||||
$ kafka-consumer-groups.sh --bootstrap-server kafka:9092 --describe --group clickhouse
|
||||
|
||||
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
|
||||
clickhouse flows-v1 0 5650351527 5650374314 22787 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-0-77740d0a-79b7-4bef-a501-25a819c3cee4 /240.0.4.8 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-0
|
||||
clickhouse flows-v1 3 3035602619 3035628290 25671 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-3-1e4629b0-69a3-48dd-899a-20f4b16be0a2 /240.0.4.8 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-3
|
||||
clickhouse flows-v1 2 1645914467 1645930257 15790 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-2-79c9bafe-fd36-42fe-921f-a802d46db684 /240.0.4.8 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-2
|
||||
clickhouse flows-v1 1 889117276 889129896 12620 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-1-f0421bbe-ba13-49df-998f-83e49045be00 /240.0.4.8 ClickHouse-ee97b7e7e5e0-default-flows_1_raw-1
|
||||
```
|
||||
|
||||
4
console/data/docs/design.svg
Normal file
4
console/data/docs/design.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 554 KiB |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@mdi/font": "6.x",
|
||||
"bootstrap": "^5.1.3"
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
{{ define "title" }}Documentation{{ end }}
|
||||
{{ define "stylesheets" }}
|
||||
<link href="{{ .RootPath }}/assets/stylesheets/docs.css" rel="stylesheet">
|
||||
{{ end }}
|
||||
{{ define "content" }}
|
||||
<div class="container-xxl">
|
||||
<div class="row">
|
||||
<div class="mb-3 col-12 col-md-3 col-lg-2">
|
||||
<nav class="shadow-sm bg-light py-2 px-3 ak-docs-toc">
|
||||
<strong>Documentation</strong>
|
||||
<ul>
|
||||
{{ range .TOC }}
|
||||
<li><a href="{{ .Name }}">{{ (index .Headers 0).Title }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-12 col-md-9 col-lg-8 px-1 px-md-5 ak-docs-markdown">
|
||||
{{ .Markdown }}
|
||||
</div>
|
||||
<div class="col-2 d-none d-lg-block">
|
||||
<nav class="shadow-sm bg-light py-2 px-3 ak-docs-toc">
|
||||
<strong>Table of content</strong>
|
||||
<ul>
|
||||
{{ $root := . }}
|
||||
{{ range .TOC }}
|
||||
{{ if eq .Name ($root.CurrentPath | trimPrefix "/docs/") }}
|
||||
{{ range .Headers }}
|
||||
{{ if ge .Level 2 }}
|
||||
<li><a class="ms-{{ sub .Level 2 }} d-inline-block"
|
||||
href="#{{ .ID }}">{{ .Title }}</a></li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,4 +0,0 @@
|
||||
{{ define "title" }}Dummy test{{ end }}
|
||||
{{ define "content" }}
|
||||
Hello there!
|
||||
{{ end }}
|
||||
@@ -1,24 +0,0 @@
|
||||
{{ define "base" }}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="{{ .RootPath }}/assets/stylesheets/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ .RootPath }}/assets/stylesheets/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="{{ .RootPath }}/assets/stylesheets/akvorado.css" rel="stylesheet">
|
||||
{{ block "stylesheets" . }}{{ end }}
|
||||
<link href="{{ .RootPath }}/assets/images/akvorado.svg" rel="icon">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>{{ template "title" . }}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{ template "navigation.html" . }}
|
||||
<main class="container-fluid pt-4">
|
||||
{{ template "content" . }}
|
||||
</main>
|
||||
</body>
|
||||
<script src="{{ .RootPath }}/assets/javascript/bootstrap.bundle.min.js"></script>
|
||||
{{ block "scripts" . }}{{ end }}
|
||||
</script>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -1,29 +0,0 @@
|
||||
<header class="navbar navbar-expand-sm navbar-light py-1 shadow-sm ak-navbar">
|
||||
<nav class="container-xxl flex-wrap flex-sm-nowrap" aria-="Main navigation">
|
||||
<a class="navbar-brand p-0 me-2"
|
||||
href="{{ .RootPath }}"
|
||||
aria-label="Akvorado">
|
||||
<img alt="Akvorado logo"
|
||||
height="40"
|
||||
src="{{ .RootPath }}/assets/images/akvorado.svg">
|
||||
Akvorado
|
||||
</a>
|
||||
<button class="navbar-toggler collapsed" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#akNavbar"
|
||||
aria-controls="akNavbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="mdi mdi-menu"></i>
|
||||
</button>
|
||||
<div class="navbar-collapse collapse" id="akNavbar">
|
||||
<ul class="navbar-nav flex-row flex-wrap pt-2 py-sm-0 ms-sm-auto">
|
||||
<li class="navitem col-6 col-sm-auto">
|
||||
<a class="nav-link pt-2{{ if eq .CurrentPath "/" }} active{{ end }}"
|
||||
href="{{ .RootPath }}"><i class="mdi mdi-home"> </i>Home</a>
|
||||
</li>
|
||||
<li class="navitem col-6 col-sm-auto">
|
||||
<a class="nav-link pt-2{{ if .CurrentPath | hasPrefix "/docs" }} active{{ end }}"
|
||||
href="{{ .RootPath }}/docs/intro"><i class="mdi mdi-book-open-variant"> </i>Docs</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -1,13 +0,0 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@mdi/font@6.x":
|
||||
version "6.6.96"
|
||||
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-6.6.96.tgz#4eee6faee5f44d3ec401d354fb95775cd6699575"
|
||||
integrity sha512-FbcvG9z17hwZ7IwX5XeOR1UYGoLq+gTKq6XNPvJFuCpn599GdiPCJbAmmDBJb+jMYXjKYr0lCxfouWGxDA82sA==
|
||||
|
||||
bootstrap@^5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.3.tgz#ba081b0c130f810fa70900acbc1c6d3c28fa8f34"
|
||||
integrity sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==
|
||||
@@ -3,8 +3,10 @@ package console
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@@ -16,6 +18,7 @@ import (
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/text"
|
||||
"github.com/yuin/goldmark/util"
|
||||
)
|
||||
@@ -28,26 +31,20 @@ var (
|
||||
|
||||
// Header describes a document header.
|
||||
type Header struct {
|
||||
Level int
|
||||
ID string
|
||||
Title string
|
||||
Level int `json:"level"`
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// DocumentTOC describes the TOC of a document
|
||||
type DocumentTOC struct {
|
||||
Name string
|
||||
Headers []Header
|
||||
}
|
||||
|
||||
type templateDocData struct {
|
||||
templateBaseData
|
||||
Markdown template.HTML
|
||||
TOC []DocumentTOC
|
||||
Name string `json:"name"`
|
||||
Headers []Header `json:"headers"`
|
||||
}
|
||||
|
||||
func (c *Component) docsHandlerFunc(w http.ResponseWriter, req *http.Request) {
|
||||
docs := c.embedOrLiveFS(embeddedDocs, "data/docs")
|
||||
rpath := strings.TrimPrefix(req.URL.Path, "/docs/")
|
||||
rpath := strings.TrimPrefix(req.URL.Path, "/api/v0/docs/")
|
||||
rpath = strings.Trim(rpath, "/")
|
||||
|
||||
var markdown []byte
|
||||
@@ -107,15 +104,21 @@ func (c *Component) docsHandlerFunc(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
md := goldmark.New(
|
||||
goldmark.WithRendererOptions(
|
||||
html.WithUnsafe(),
|
||||
),
|
||||
goldmark.WithExtensions(
|
||||
extension.Footnote,
|
||||
extension.Typographer,
|
||||
highlighting.Highlighting,
|
||||
highlighting.NewHighlighting(
|
||||
highlighting.WithStyle("dracula"),
|
||||
),
|
||||
),
|
||||
goldmark.WithParserOptions(
|
||||
parser.WithAutoHeadingID(),
|
||||
parser.WithASTTransformers(
|
||||
util.Prioritized(&internalLinkTransformer{}, 500),
|
||||
util.Prioritized(&imageEmbedder{docs}, 500),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -126,13 +129,13 @@ func (c *Component) docsHandlerFunc(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Cache-Control", "max-age=300")
|
||||
c.renderTemplate(w, "docs.html", templateDocData{
|
||||
templateBaseData: templateBaseData{
|
||||
RootPath: "..",
|
||||
CurrentPath: req.URL.Path,
|
||||
},
|
||||
Markdown: template.HTML(buf.String()),
|
||||
TOC: toc,
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetIndent("", " ")
|
||||
encoder.SetEscapeHTML(false)
|
||||
encoder.Encode(map[string]interface{}{
|
||||
"markdown": buf.String(),
|
||||
"toc": toc,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -155,6 +158,37 @@ func (r *internalLinkTransformer) Transform(node *ast.Document, reader text.Read
|
||||
ast.Walk(node, replaceLinks)
|
||||
}
|
||||
|
||||
type imageEmbedder struct {
|
||||
root fs.FS
|
||||
}
|
||||
|
||||
func (r *imageEmbedder) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
|
||||
replaceLinks := func(n ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||
if !entering {
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
switch node := n.(type) {
|
||||
case *ast.Image:
|
||||
path := string(node.Destination)
|
||||
if strings.Index(path, "/") != -1 || !strings.HasSuffix(path, ".svg") {
|
||||
break
|
||||
}
|
||||
f, err := r.root.Open(path)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
content, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
encoded := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(content))
|
||||
node.Destination = []byte(encoded)
|
||||
}
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
ast.Walk(node, replaceLinks)
|
||||
}
|
||||
|
||||
type tocLogger struct {
|
||||
headers []Header
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"akvorado/common/daemon"
|
||||
"akvorado/common/http"
|
||||
"akvorado/common/reporter"
|
||||
)
|
||||
@@ -18,31 +17,42 @@ func TestServeDocs(t *testing.T) {
|
||||
if !live {
|
||||
name = "embeddedfs"
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
r := reporter.NewMock(t)
|
||||
h := http.NewMock(t, r)
|
||||
_, err := New(r, Configuration{
|
||||
ServeLiveFS: live,
|
||||
}, Dependencies{
|
||||
HTTP: h,
|
||||
Daemon: daemon.NewMock(t),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error:\n%+v", err)
|
||||
}
|
||||
cases := []struct {
|
||||
Path string
|
||||
Expect string
|
||||
}{
|
||||
{"usage", `<a href=\"configuration\">configuration section</a>`},
|
||||
{"intro", `data:image/svg`},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%s-%s", name, tc.Path), func(t *testing.T) {
|
||||
r := reporter.NewMock(t)
|
||||
h := http.NewMock(t, r)
|
||||
_, err := New(r, Configuration{
|
||||
ServeLiveFS: live,
|
||||
}, Dependencies{
|
||||
HTTP: h,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error:\n%+v", err)
|
||||
}
|
||||
|
||||
resp, err := netHTTP.Get(fmt.Sprintf("http://%s/docs/usage", h.Address))
|
||||
if err != nil {
|
||||
t.Fatalf("GET /docs/usage:\n%+v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("GET /docs/usage: got status code %d, not 200", resp.StatusCode)
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
if strings.Contains(string(body), "configuration.md") {
|
||||
t.Errorf("GET /docs/usage: contains %q while it should not", "configuration.md")
|
||||
}
|
||||
})
|
||||
resp, err := netHTTP.Get(fmt.Sprintf("http://%s/api/v0/docs/%s",
|
||||
h.Address, tc.Path))
|
||||
if err != nil {
|
||||
t.Fatalf("GET /api/v0/docs/%s:\n%+v", tc.Path, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("GET /api/v0/docs/%s: got status code %d, not 200",
|
||||
tc.Path, resp.StatusCode)
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
if !strings.Contains(string(body), tc.Expect) {
|
||||
t.Errorf("GET /api/v0/docs/%s: does not contain %q",
|
||||
tc.Path, tc.Expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
console/frontend/.gitignore
vendored
Normal file
24
console/frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
13
console/frontend/index.html
Normal file
13
console/frontend/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="h-screen scroll-pt-60">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/src/assets/images/akvorado.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Akvorado</title>
|
||||
</head>
|
||||
<body class="bg-white text-gray-900 dark:bg-gray-800 dark:text-gray-100">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
25
console/frontend/package.json
Normal file
25
console/frontend/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "akvorado",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.5.0",
|
||||
"@heroicons/vue": "^1.0.6",
|
||||
"notiwind": "^1.2.5",
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.2",
|
||||
"@vitejs/plugin-vue": "^2.3.0",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"postcss": "^8.4.12",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"vite": "^2.9.0"
|
||||
}
|
||||
}
|
||||
6
console/frontend/postcss.config.js
Normal file
6
console/frontend/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
14
console/frontend/src/App.vue
Normal file
14
console/frontend/src/App.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<Notifications />
|
||||
<Navigation />
|
||||
<main>
|
||||
<router-view />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import './tailwind.css';
|
||||
|
||||
import Navigation from "./components/Navigation.vue";
|
||||
import Notifications from "./components/Notifications.vue";
|
||||
</script>
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
33
console/frontend/src/components/DarkMode.vue
Normal file
33
console/frontend/src/components/DarkMode.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<button type="button"
|
||||
@click="toggle()"
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5">
|
||||
<MoonIcon class="w-5 h-5" v-if="!dark" />
|
||||
<SunIcon class="w-5 h-5" v-if="dark" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { SunIcon, MoonIcon } from '@heroicons/vue/solid';
|
||||
|
||||
const dark = ref(false);
|
||||
|
||||
if (localStorage.getItem('color-theme') === 'dark' ||
|
||||
(!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
dark.value = true;
|
||||
}
|
||||
|
||||
watch(dark, (dark) => {
|
||||
if (dark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
const toggle = () => {
|
||||
dark.value = !dark.value;
|
||||
localStorage.setItem('color-theme', dark.value?'dark':'light');
|
||||
}
|
||||
</script>
|
||||
48
console/frontend/src/components/Navigation.vue
Normal file
48
console/frontend/src/components/Navigation.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<Disclosure as="nav"
|
||||
v-slot="{ open }"
|
||||
class="w-full relative z-40 bg-gradient-to-r from-blue-100 to-indigo-200 border-gray-200 px-2 sm:px-4 py-2.5 dark:from-gray-800 dark:to-gray-600 shadow">
|
||||
<div class="container flex flex-wrap justify-between items-center mx-auto">
|
||||
<router-link to="/" class="flex items-center">
|
||||
<img src="../assets/images/akvorado.svg" class="mr-3 h-6 sm:h-9" alt="Akvorado Logo" />
|
||||
<span class="self-center text-xl font-semibold whitespace-nowrap dark:text-white">Akvorado</span>
|
||||
</router-link>
|
||||
<div class="flex md:order-2">
|
||||
<DarkMode />
|
||||
<DisclosureButton class="inline-flex items-center p-2 ml-3 text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<MenuIcon v-if="!open" class="w-6 h-6" />
|
||||
<XIcon v-else class="w-6 h-6" />
|
||||
</DisclosureButton>
|
||||
</div>
|
||||
<DisclosurePanel static class="justify-between items-center w-full md:block md:w-auto md:order-1"
|
||||
:class="open?'block':'hidden'">
|
||||
<ul class="flex flex-col mt-4 md:flex-row md:space-x-8 md:mt-0 md:text-sm md:font-medium">
|
||||
<li v-for="item in navigation" :key="item.name">
|
||||
<router-link class="block py-2 pr-4 pl-3 rounded"
|
||||
:class="item.current?['text-white bg-blue-700 md:bg-transparent md:text-blue-700 dark:text-white']:['text-gray-700 hover:bg-gray-50 md:hover:text-blue-700 dark:text-gray-400 md:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white dark:border-gray-700']"
|
||||
:to="item.link"
|
||||
:aria-current="item.current && 'page'">
|
||||
<component :is="item.icon" class="w-5 h-5 inline"></component>
|
||||
{{ item.name }}
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</DisclosurePanel>
|
||||
</div>
|
||||
</Disclosure>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue';
|
||||
import { HomeIcon, BookOpenIcon, MenuIcon, XIcon } from '@heroicons/vue/solid';
|
||||
import DarkMode from './DarkMode.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const navigation = computed(() => [
|
||||
{ name: 'Home', icon: HomeIcon, link: '/', current: route.path == '/' },
|
||||
{ name: 'Documentation', icon: BookOpenIcon, link: '/docs', current: route.path.startsWith('/docs') },
|
||||
]);
|
||||
</script>
|
||||
46
console/frontend/src/components/Notifications.vue
Normal file
46
console/frontend/src/components/Notifications.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<NotificationGroup group="top">
|
||||
<div class="fixed z-50 inset-0 flex items-start justify-center p-6 px-4 py-6 pointer-events-none">
|
||||
<div class="w-full max-w-sm">
|
||||
<Notification
|
||||
v-slot="{ notifications, close }"
|
||||
enter="transform ease-out duration-300 transition"
|
||||
enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
|
||||
enter-to="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave="transition ease-in duration-500"
|
||||
leave-from="opacity-100"
|
||||
leave-to="opacity-0"
|
||||
move="transition duration-500"
|
||||
move-delay="delay-300">
|
||||
<div
|
||||
class="flex w-full max-w-sm mx-auto mt-4 overflow-hidden bg-stone-100 dark:bg-stone-800 rounded-lg shadow-md pointer-events-auto"
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id">
|
||||
<div
|
||||
class="flex w-6"
|
||||
:class="{'bg-red-500': notification.kind === 'error',
|
||||
'bg-green-500': notification.kind === 'success',
|
||||
'bg-blue-500': notification.kind === 'info'}">
|
||||
</div>
|
||||
<div class="ml-3 w-0 flex-1 py-4">
|
||||
<p class="font-semibold text-gray-800 dark:text-gray-300">{{ notification.title }}</p>
|
||||
<p class="text-sm">{{ notification.text }}</p>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 ml-4 p-2 h-full">
|
||||
<button
|
||||
@click="close(notification.id)"
|
||||
class="inline-flex text-gray-400 rounded-md hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:focus:ring-gray-600">
|
||||
<span class="sr-only">Close</span>
|
||||
<XIcon class="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Notification>
|
||||
</div>
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { XIcon } from '@heroicons/vue/solid';
|
||||
</script>
|
||||
9
console/frontend/src/main.js
Normal file
9
console/frontend/src/main.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createApp } from 'vue';
|
||||
import Notifications from 'notiwind'
|
||||
import App from './App.vue';
|
||||
import router from "./router";
|
||||
|
||||
createApp(App)
|
||||
.use(router)
|
||||
.use(Notifications)
|
||||
.mount('#app');
|
||||
16
console/frontend/src/router/index.js
Normal file
16
console/frontend/src/router/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import {createRouter, createWebHistory} from 'vue-router';
|
||||
import Home from '../views/Home.vue';
|
||||
import Doc from '../views/Doc.vue';
|
||||
import NotFound from '../views/NotFound.vue';
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{ path: "/", name: "Home", component: Home },
|
||||
{ path: "/docs", redirect: "/docs/intro" },
|
||||
{ path: "/docs/:id", name: "Documentation", component: Doc },
|
||||
{ path: "/:pathMatch(.*)", component: NotFound }
|
||||
],
|
||||
});
|
||||
|
||||
export default router;
|
||||
3
console/frontend/src/tailwind.css
Normal file
3
console/frontend/src/tailwind.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
86
console/frontend/src/views/Doc.vue
Normal file
86
console/frontend/src/views/Doc.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="w-full flex-none md:grid md:grid-cols-3 md:gap-8">
|
||||
<div class="fixed top-0 h-full overflow-y-auto bg-gray-50 dark:bg-gray-900 dark:text-gray-200 md:mx-0 py-20 px-4 sm:px-6 md:pl-0 md:pr-8">
|
||||
<nav class="text-sm max-w-[37.5rem] mx-auto md:max-w-none md:mx-0 relative">
|
||||
<ul class="space-y-8 pl-6">
|
||||
<li v-for="document in toc" :key="document.name" class="space-y-3">
|
||||
<router-link :to="{path: document.name, hash: `#${document.headers[0].id}` }"
|
||||
class="block font-semibold"
|
||||
:class="{ 'text-blue-600': activeDocument === document.name,
|
||||
'dark:text-blue-300': activeDocument === document.name,
|
||||
'text-gray-900': activeDocument !== document.name,
|
||||
'dark:text-gray-300': activeDocument !== document.name }">
|
||||
{{ document.headers[0].title }}
|
||||
</router-link>
|
||||
<ul class="space-y-3">
|
||||
<template v-for="header in document.headers">
|
||||
<li v-if="header.level >= 2 && header.level <= 3"
|
||||
:class="{'ml-2': (header.level == 2), 'ml-4': (header.level == 3)}">
|
||||
<router-link
|
||||
:to="{path: document.name, hash: `#${header.id}` }" class="block"
|
||||
:class="{ 'text-blue-600': activeDocument === document.name && activeSlug === header.id,
|
||||
'dark:text-blue-300': activeDocument === document.name && activeSlug === header.id }">
|
||||
{{ header.title }}
|
||||
</router-link>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-span-2 md:-ml-8 md:shadow-md">
|
||||
<div class="py-4 px-4 md:px-16">
|
||||
<div class="prose prose-sm md:prose-base max-w-[37.5rem] mx-auto dark:prose-invert prose-h1:border-b-2 dark:prose-h1:border-gray-700 prose-img:center prose-pre:rounded"
|
||||
v-html="markdown">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { notify } from "notiwind";
|
||||
|
||||
const route = useRoute();
|
||||
const markdown = ref('');
|
||||
const toc = ref([]);
|
||||
const activeDocument = ref(null);
|
||||
const activeSlug = computed(() => route.hash.replace(/^#/, ''));
|
||||
|
||||
watch(() => ({ id: route.params.id, hash: route.hash }),
|
||||
async (to, from) => {
|
||||
if (to.id !== from?.id) {
|
||||
const id = to.id;
|
||||
try {
|
||||
const response = await fetch(`/api/v0/docs/${id}`);
|
||||
if (!response.ok) {
|
||||
throw `got a ${response.status} error`;
|
||||
}
|
||||
const data = await response.json();
|
||||
markdown.value = data.markdown;
|
||||
toc.value = data.toc;
|
||||
activeDocument.value = id;
|
||||
} catch (error) {
|
||||
console.error(`while retrieving ${id}:`, error);
|
||||
markdown.value = "hello";
|
||||
markdown.toc = [];
|
||||
activeDocument.value = "nothing";
|
||||
}
|
||||
}
|
||||
if (to.id !== from?.id || to.hash !== from?.hash) {
|
||||
if (to.hash === "") {
|
||||
window.scrollTo(0, 0);
|
||||
} else {
|
||||
await nextTick();
|
||||
const el = document.querySelector(to.hash);
|
||||
if (el !== null) {
|
||||
window.scrollTo(0, el.getBoundingClientRect().top + window.pageYOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
</script>
|
||||
3
console/frontend/src/views/Home.vue
Normal file
3
console/frontend/src/views/Home.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<img class="mt-10 mx-auto" src="../assets/images/akvorado.svg">
|
||||
</template>
|
||||
4
console/frontend/src/views/NotFound.vue
Normal file
4
console/frontend/src/views/NotFound.vue
Normal file
@@ -0,0 +1,4 @@
|
||||
<template>
|
||||
<img class="mt-10 mx-auto" src="../assets/images/akvorado.svg">
|
||||
<h1 class="mt-10 text-center font-bold text-5xl">Not found!</h1>
|
||||
</template>
|
||||
13
console/frontend/tailwind.config.js
Normal file
13
console/frontend/tailwind.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
content: [
|
||||
'./index.html',
|
||||
'./src/**/*.{vue,js,ts,jsx,tsx}',
|
||||
],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/typography'),
|
||||
],
|
||||
}
|
||||
19
console/frontend/vite.config.js
Normal file
19
console/frontend/vite.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
outDir: "../data/frontend",
|
||||
emptyOutDir: true,
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
973
console/frontend/yarn.lock
Normal file
973
console/frontend/yarn.lock
Normal file
@@ -0,0 +1,973 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
|
||||
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.16.7"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
|
||||
integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
|
||||
|
||||
"@babel/highlight@^7.16.7":
|
||||
version "7.16.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
|
||||
integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.16.7"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.16.4":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.8.tgz#2817fb9d885dd8132ea0f8eb615a6388cca1c240"
|
||||
integrity sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==
|
||||
|
||||
"@headlessui/vue@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/vue/-/vue-1.5.0.tgz#8cd4877d3d344e482073a04ae8e3b7f987bb267c"
|
||||
integrity sha512-jAp6XYpqdEv32xhszaj5ejvjaX5qhu20sCbxu7lplePEfZL+4ffabivJBBTZAiPWczqAXmnZWNWG5DOyqjRa4w==
|
||||
|
||||
"@heroicons/vue@^1.0.6":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@heroicons/vue/-/vue-1.0.6.tgz#d8b90734b436eb5a87f40cc300b64a0fb0031f7f"
|
||||
integrity sha512-ng2YcCQrdoQWEFpw+ipFl2rZo8mZ56v0T5+MyfQQvNqfKChwgP6DMloZLW+rl17GEcHkE3H82UTAMKBKZr4+WA==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
|
||||
"@nodelib/fs.walk@^1.2.3":
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
|
||||
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
|
||||
dependencies:
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@tailwindcss/typography@^0.5.2":
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.2.tgz#24b069dab24d7a2467d01aca0dd432cb4b29f0ee"
|
||||
integrity sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==
|
||||
dependencies:
|
||||
lodash.castarray "^4.4.0"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.merge "^4.6.2"
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@vitejs/plugin-vue@^2.3.0":
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.1.tgz#5f286b8d3515381c6d5c8fa8eee5e6335f727e14"
|
||||
integrity sha512-YNzBt8+jt6bSwpt7LP890U1UcTOIZZxfpE5WOJ638PNxSEKOqAi0+FSKS0nVeukfdZ0Ai/H7AFd6k3hayfGZqQ==
|
||||
|
||||
"@vue/compiler-core@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.31.tgz#d38f06c2cf845742403b523ab4596a3fda152e89"
|
||||
integrity sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/shared" "3.2.31"
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-dom@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz#b1b7dfad55c96c8cc2b919cd7eb5fd7e4ddbf00e"
|
||||
integrity sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
"@vue/compiler-sfc@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz#d02b29c3fe34d599a52c5ae1c6937b4d69f11c2f"
|
||||
integrity sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.31"
|
||||
"@vue/compiler-dom" "3.2.31"
|
||||
"@vue/compiler-ssr" "3.2.31"
|
||||
"@vue/reactivity-transform" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-ssr@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz#4fa00f486c9c4580b40a4177871ebbd650ecb99c"
|
||||
integrity sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
"@vue/devtools-api@^6.0.0":
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.1.4.tgz#b4aec2f4b4599e11ba774a50c67fa378c9824e53"
|
||||
integrity sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==
|
||||
|
||||
"@vue/reactivity-transform@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz#0f5b25c24e70edab2b613d5305c465b50fc00911"
|
||||
integrity sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.31.tgz#fc90aa2cdf695418b79e534783aca90d63a46bbd"
|
||||
integrity sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==
|
||||
dependencies:
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
"@vue/runtime-core@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.31.tgz#9d284c382f5f981b7a7b5971052a1dc4ef39ac7a"
|
||||
integrity sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==
|
||||
dependencies:
|
||||
"@vue/reactivity" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
"@vue/runtime-dom@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz#79ce01817cb3caf2c9d923f669b738d2d7953eff"
|
||||
integrity sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==
|
||||
dependencies:
|
||||
"@vue/runtime-core" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/server-renderer@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.31.tgz#201e9d6ce735847d5989403af81ef80960da7141"
|
||||
integrity sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==
|
||||
dependencies:
|
||||
"@vue/compiler-ssr" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
"@vue/shared@3.2.31":
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.31.tgz#c90de7126d833dcd3a4c7534d534be2fb41faa4e"
|
||||
integrity sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==
|
||||
|
||||
acorn-node@^1.6.1:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
|
||||
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
|
||||
dependencies:
|
||||
acorn "^7.0.0"
|
||||
acorn-walk "^7.0.0"
|
||||
xtend "^4.0.2"
|
||||
|
||||
acorn-walk@^7.0.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||
|
||||
acorn@^7.0.0:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
anymatch@~3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
|
||||
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
arg@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
|
||||
integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==
|
||||
|
||||
autoprefixer@^10.4.4:
|
||||
version "10.4.4"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.4.tgz#3e85a245b32da876a893d3ac2ea19f01e7ea5a1e"
|
||||
integrity sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==
|
||||
dependencies:
|
||||
browserslist "^4.20.2"
|
||||
caniuse-lite "^1.0.30001317"
|
||||
fraction.js "^4.2.0"
|
||||
normalize-range "^0.1.2"
|
||||
picocolors "^1.0.0"
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.20.2:
|
||||
version "4.20.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88"
|
||||
integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001317"
|
||||
electron-to-chromium "^1.4.84"
|
||||
escalade "^3.1.1"
|
||||
node-releases "^2.0.2"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
camelcase-css@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
|
||||
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
|
||||
|
||||
caniuse-lite@^1.0.30001317:
|
||||
version "1.0.30001325"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz#2b4ad19b77aa36f61f2eaf72e636d7481d55e606"
|
||||
integrity sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==
|
||||
|
||||
chalk@^2.0.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||
dependencies:
|
||||
color-name "1.1.3"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
color-name@^1.1.4, color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
cosmiconfig@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
|
||||
integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
|
||||
dependencies:
|
||||
"@types/parse-json" "^4.0.0"
|
||||
import-fresh "^3.2.1"
|
||||
parse-json "^5.0.0"
|
||||
path-type "^4.0.0"
|
||||
yaml "^1.10.0"
|
||||
|
||||
cssesc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||
|
||||
csstype@^2.6.8:
|
||||
version "2.6.20"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
|
||||
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
|
||||
|
||||
defined@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
|
||||
|
||||
detective@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b"
|
||||
integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==
|
||||
dependencies:
|
||||
acorn-node "^1.6.1"
|
||||
defined "^1.0.0"
|
||||
minimist "^1.1.1"
|
||||
|
||||
didyoumean@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
||||
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
|
||||
|
||||
dlv@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
||||
|
||||
electron-to-chromium@^1.4.84:
|
||||
version "1.4.103"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz#abfe376a4d70fa1e1b4b353b95df5d6dfd05da3a"
|
||||
integrity sha512-c/uKWR1Z/W30Wy/sx3dkZoj4BijbXX85QKWu9jJfjho3LBAXNEGAEW3oWiGb+dotA6C6BzCTxL2/aLes7jlUeg==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
esbuild-android-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.30.tgz#9efcdb3d826b9c67705a0c518d361ab44ae4cc5b"
|
||||
integrity sha512-vdJ7t8A8msPfKpYUGUV/KaTQRiZ0vDa2XSTlzXVkGGVHLKPeb85PBUtYJcEgw3htW3IdX5i1t1IMdQCwJJgNAg==
|
||||
|
||||
esbuild-android-arm64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.30.tgz#7b90fa7578b94da047e0bf3da477cb5775b58664"
|
||||
integrity sha512-BdgGfxeA5hBQNErLr7BWJUA8xjflEfyaARICy8e0OJYNSAwDbEzOf8LyiKWSrDcgV129mWhi3VpbNQvOIDEHcg==
|
||||
|
||||
esbuild-darwin-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.30.tgz#275e40eb100286b868d4cd664e6447b53400f7ff"
|
||||
integrity sha512-VRaOXMMrsG5n53pl4qFZQdXy2+E0NoLP/QH3aDUI0+bQP+ZHDmbINKcDy2IX7GVFI9kqPS18iJNAs5a6/G2LZg==
|
||||
|
||||
esbuild-darwin-arm64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.30.tgz#c2b8fe03fb0dcee1d227b226c9c921de71e4d411"
|
||||
integrity sha512-qDez+fHMOrO9Oc9qjt/x+sy09RJVh62kik5tVybKRLmezeV4qczM9/sAYY57YN0aWLdHbcCj2YqJUWYJNsgKnw==
|
||||
|
||||
esbuild-freebsd-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.30.tgz#328bb272ce6cfcae202b6e0a06c240036335cc91"
|
||||
integrity sha512-mec1jENcImVVagddZlGWsdAUwBnzR5cgnhzCxv+9fSMxKbx1uZYLLUAnLPp8m/i934zrumR1xGjJ5VoWdPlI2w==
|
||||
|
||||
esbuild-freebsd-arm64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.30.tgz#49ce79fa7d7087a941e27432da46bafb5b35a979"
|
||||
integrity sha512-cpjbTs6Iok/AfeB0JgTzyUJTMStC1SQULmany5nHx6S4GTkSgaAHuJzZO0GcVWqghI4e0YL/bjXAhN5Mn6feNw==
|
||||
|
||||
esbuild-linux-32@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.30.tgz#c473299f5291130f6d4436808603b529ccbfa785"
|
||||
integrity sha512-liIONVT4F2kZmOMwtwASqZ8WkIjb5HHBR9HUffdHiuotSTF3CyZO+EJf+Og+SYYuuVIvt0qHNSFjBA/iSESteQ==
|
||||
|
||||
esbuild-linux-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.30.tgz#b4be59f0665a44574a7617c9db673943da6061f8"
|
||||
integrity sha512-LUnpzoMpRqFON5En4qEj6NWiyH6a1K+Y2qYNKrCy5qPTjDoG/EWeqMz69n8Uv7pRuvDKl3FNGJ1dufTrA5i0sw==
|
||||
|
||||
esbuild-linux-arm64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.30.tgz#78485a9f49858ea69ced85c3dd0fe58d354f20f8"
|
||||
integrity sha512-DHZHn6FK5q/KL0fpNT/0jE38Nnyk2rXxKE9WENi95EXtqfOLPgE8tzjTZQNgpr61R95QX4ymQU26ni3IZk8buQ==
|
||||
|
||||
esbuild-linux-arm@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.30.tgz#00392bbe04ac687dd6d9849ecee302bc27f984f2"
|
||||
integrity sha512-97T+bbXnpqf7mfIG49UR7ZSJFGgvc22byn74qw3Kx2GDCBSQoVFjyWuKOHGXp8nXk3XYrdFF+mQ8yQ7aNsgQvg==
|
||||
|
||||
esbuild-linux-mips64le@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.30.tgz#cf48a292037c3a9ca3ca84ec0ae4f47bf1247ab4"
|
||||
integrity sha512-fLUzTFZ7uknC0aPTk7/lM7NmaG/9ZqE3SaHEphcaM009SZK/mDOvZugWi1ss6WGNhk13dUrhkfHcc4FSb9hYhg==
|
||||
|
||||
esbuild-linux-ppc64le@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.30.tgz#8e448a54e7040829ee9ecfc68dab0f3a039b1cff"
|
||||
integrity sha512-2Oudm2WEfj0dNU9bzIl5L/LrsMEmHWsOsYgJJqu8fDyUDgER+J1d33qz3cUdjsJk7gAENayIxDSpsuCszx0w3A==
|
||||
|
||||
esbuild-linux-riscv64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.30.tgz#118af007f21adb00c4362d5eda3f004290f4d0ef"
|
||||
integrity sha512-RPMucPW47rV4t2jlelaE948iCRtbZf5RhifxSwzlpM1Mqdyu99MMNK0w4jFreGTmLN+oGomxIOxD6n+2E/XqHw==
|
||||
|
||||
esbuild-linux-s390x@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.30.tgz#e0649e26d8791bf6265685842dcef732de59b49b"
|
||||
integrity sha512-OZ68r7ok6qO7hdwrwQn2p5jbIRRcUcVaAykB7e0uCA0ODwfeGunILM6phJtq2Oz4dlEEFvd+tSuma3paQKwt+A==
|
||||
|
||||
esbuild-netbsd-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.30.tgz#7653db21ab4379a1b557f338b040e3493ff5006c"
|
||||
integrity sha512-iyejQUKn0TzpPkufq8pSCxOg9NheycQbMbPCmjefTe9wYuUlBt1TcHvdoJnYbQzsAhAh1BNq+s0ycRsIJFZzaQ==
|
||||
|
||||
esbuild-openbsd-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.30.tgz#3fad1699cb2ca7a060585356e2881df7b3fa5bb1"
|
||||
integrity sha512-UyK1MTMcy4j5fH260fsE1o6MVgWNhb62eCK2yCKCRazZv8Nqdc2WiP9ygjWidmEdCDS+A6MuVp9ozk9uoQtQpA==
|
||||
|
||||
esbuild-sunos-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.30.tgz#2306a178dc2362cf32fc182327c21b49b78ca1a3"
|
||||
integrity sha512-aQRtRTNKHB4YuG+xXATe5AoRTNY48IJg5vjE8ElxfmjO9+KdX7MHFkTLhlKevCD6rNANtB3qOlSIeAiXTwHNqw==
|
||||
|
||||
esbuild-windows-32@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.30.tgz#ea17b2a9468e346734f926a7edd49de3cc81d12f"
|
||||
integrity sha512-9/fb1tPtpacMqxAXp3fGHowUDg/l9dVch5hKmCLEZC6PdGljh6h372zMdJwYfH0Bd5CCPT0Wx95uycBLJiqpXA==
|
||||
|
||||
esbuild-windows-64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.30.tgz#266147f1f45974ac61dece10ab32bc916050dcc2"
|
||||
integrity sha512-DHgITeUhPAnN9I5O6QBa1GVyPOhiYCn4S4TtQr7sO4+X0LNyqnlmA1M0qmGkUdDC1QQfjI8uQ4G/whdWb2pWIQ==
|
||||
|
||||
esbuild-windows-arm64@0.14.30:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.30.tgz#8e5e9c2455bffaf3e1a387eee4841f5c3797b8a8"
|
||||
integrity sha512-F1kLyQH7zSgjh5eLxogGZN7C9+KNs9m+s7Q6WZoMmCWT/6j998zlaoECHyM8izJRRfsvw2eZlEa1jO6/IOU1AQ==
|
||||
|
||||
esbuild@^0.14.27:
|
||||
version "0.14.30"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.30.tgz#8bf6501a58f71e622e7485aeada79c764c1affe4"
|
||||
integrity sha512-wCecQSBkIjp2xjuXY+wcXS/PpOQo9rFh4NAKPh4Pm9f3fuLcnxkR0rDzA+mYP88FtXIUcXUyYmaIgfrzRl55jA==
|
||||
optionalDependencies:
|
||||
esbuild-android-64 "0.14.30"
|
||||
esbuild-android-arm64 "0.14.30"
|
||||
esbuild-darwin-64 "0.14.30"
|
||||
esbuild-darwin-arm64 "0.14.30"
|
||||
esbuild-freebsd-64 "0.14.30"
|
||||
esbuild-freebsd-arm64 "0.14.30"
|
||||
esbuild-linux-32 "0.14.30"
|
||||
esbuild-linux-64 "0.14.30"
|
||||
esbuild-linux-arm "0.14.30"
|
||||
esbuild-linux-arm64 "0.14.30"
|
||||
esbuild-linux-mips64le "0.14.30"
|
||||
esbuild-linux-ppc64le "0.14.30"
|
||||
esbuild-linux-riscv64 "0.14.30"
|
||||
esbuild-linux-s390x "0.14.30"
|
||||
esbuild-netbsd-64 "0.14.30"
|
||||
esbuild-openbsd-64 "0.14.30"
|
||||
esbuild-sunos-64 "0.14.30"
|
||||
esbuild-windows-32 "0.14.30"
|
||||
esbuild-windows-64 "0.14.30"
|
||||
esbuild-windows-arm64 "0.14.30"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
estree-walker@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
|
||||
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
||||
|
||||
fast-glob@^3.2.11:
|
||||
version "3.2.11"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
|
||||
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
|
||||
integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
fraction.js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob-parent@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
|
||||
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
|
||||
dependencies:
|
||||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-core-module@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
|
||||
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
lilconfig@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
|
||||
integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
lodash.castarray@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
|
||||
integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
magic-string@^0.25.7:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
||||
dependencies:
|
||||
sourcemap-codec "^1.4.8"
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimist@^1.1.1:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
nanoid@^3.3.1:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
|
||||
integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==
|
||||
|
||||
node-releases@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
|
||||
integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-range@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||
integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
|
||||
|
||||
notiwind@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/notiwind/-/notiwind-1.2.5.tgz#4a1ab3d3afa0c88f6539c6730d619feb9d528230"
|
||||
integrity sha512-i0WHk96skvQ0xt3uMeAI+tVZ2sgAOSpuNIeTycQZjwXh4DheLbpJffLjYOXT93C3CqZYVTal0hnGCpZIlG0jgQ==
|
||||
|
||||
object-hash@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
|
||||
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
|
||||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-json@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
error-ex "^1.3.1"
|
||||
json-parse-even-better-errors "^2.3.0"
|
||||
lines-and-columns "^1.1.6"
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
postcss-js@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
|
||||
integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==
|
||||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
|
||||
postcss-load-config@^3.1.0:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
||||
dependencies:
|
||||
lilconfig "^2.0.5"
|
||||
yaml "^1.10.2"
|
||||
|
||||
postcss-nested@5.0.6:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc"
|
||||
integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==
|
||||
dependencies:
|
||||
postcss-selector-parser "^6.0.6"
|
||||
|
||||
postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
|
||||
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-value-parser@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.1.10, postcss@^8.4.12, postcss@^8.4.6:
|
||||
version "8.4.12"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
|
||||
integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
|
||||
dependencies:
|
||||
nanoid "^3.3.1"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
quick-lru@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
resolve-from@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
resolve@^1.22.0:
|
||||
version "1.22.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
|
||||
integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
|
||||
dependencies:
|
||||
is-core-module "^2.8.1"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
rollup@^2.59.0:
|
||||
version "2.70.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.1.tgz#824b1f1f879ea396db30b0fc3ae8d2fead93523e"
|
||||
integrity sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
|
||||
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
source-map@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sourcemap-codec@^1.4.8:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
tailwindcss@^3.0.23:
|
||||
version "3.0.23"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
|
||||
integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
|
||||
dependencies:
|
||||
arg "^5.0.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
cosmiconfig "^7.0.1"
|
||||
detective "^5.2.0"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.11"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^2.2.0"
|
||||
postcss "^8.4.6"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.0"
|
||||
postcss-nested "5.0.6"
|
||||
postcss-selector-parser "^6.0.9"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.0"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
util-deprecate@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
vite@^2.9.0:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.1.tgz#84bce95fae210a7beb566a0af06246748066b48f"
|
||||
integrity sha512-vSlsSdOYGcYEJfkQ/NeLXgnRv5zZfpAsdztkIrs7AZHV8RCMZQkwjo4DS5BnrYTqoWqLoUe1Cah4aVO4oNNqCQ==
|
||||
dependencies:
|
||||
esbuild "^0.14.27"
|
||||
postcss "^8.4.12"
|
||||
resolve "^1.22.0"
|
||||
rollup "^2.59.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vue-router@^4.0.14:
|
||||
version "4.0.14"
|
||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.14.tgz#ce2028c1c5c33e30c7287950c973f397fce1bd65"
|
||||
integrity sha512-wAO6zF9zxA3u+7AkMPqw9LjoUCjSxfFvINQj3E/DceTt6uEz1XZLraDhdg2EYmvVwTBSGlLYsUw8bDmx0754Mw==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.0.0"
|
||||
|
||||
vue@^3.2.25:
|
||||
version "3.2.31"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.31.tgz#e0c49924335e9f188352816788a4cca10f817ce6"
|
||||
integrity sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.31"
|
||||
"@vue/compiler-sfc" "3.2.31"
|
||||
"@vue/runtime-dom" "3.2.31"
|
||||
"@vue/server-renderer" "3.2.31"
|
||||
"@vue/shared" "3.2.31"
|
||||
|
||||
xtend@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
yaml@^1.10.0, yaml@^1.10.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
@@ -16,9 +16,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"gopkg.in/tomb.v2"
|
||||
|
||||
"akvorado/common/daemon"
|
||||
"akvorado/common/http"
|
||||
"akvorado/common/reporter"
|
||||
)
|
||||
@@ -27,7 +25,6 @@ import (
|
||||
type Component struct {
|
||||
r *reporter.Reporter
|
||||
d *Dependencies
|
||||
t tomb.Tomb
|
||||
config Configuration
|
||||
|
||||
templates map[string]*template.Template
|
||||
@@ -36,8 +33,7 @@ type Component struct {
|
||||
|
||||
// Dependencies define the dependencies of the console component.
|
||||
type Dependencies struct {
|
||||
Daemon daemon.Component
|
||||
HTTP *http.Component
|
||||
HTTP *http.Component
|
||||
}
|
||||
|
||||
// New creates a new console component.
|
||||
@@ -47,10 +43,6 @@ func New(reporter *reporter.Reporter, config Configuration, dependencies Depende
|
||||
d: &dependencies,
|
||||
config: config,
|
||||
}
|
||||
c.d.Daemon.Track(&c.t, "console")
|
||||
if err := c.loadTemplates(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Grafana proxy
|
||||
if c.config.GrafanaURL != "" {
|
||||
@@ -74,35 +66,12 @@ func New(reporter *reporter.Reporter, config Configuration, dependencies Depende
|
||||
c.d.HTTP.AddHandler("/grafana/", proxyHandler)
|
||||
}
|
||||
|
||||
c.d.HTTP.AddHandler("/docs/", netHTTP.HandlerFunc(c.docsHandlerFunc))
|
||||
c.d.HTTP.AddHandler("/assets/", netHTTP.HandlerFunc(c.assetsHandlerFunc))
|
||||
c.d.HTTP.AddHandler("/", netHTTP.HandlerFunc(c.assetsHandlerFunc))
|
||||
c.d.HTTP.AddHandler("/api/v0/docs/", netHTTP.HandlerFunc(c.docsHandlerFunc))
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Start starts the web component.
|
||||
func (c *Component) Start() error {
|
||||
c.r.Info().Msg("starting console component")
|
||||
if err := c.watchTemplates(); err != nil {
|
||||
return err
|
||||
}
|
||||
c.t.Go(func() error {
|
||||
select {
|
||||
case <-c.t.Dying():
|
||||
return nil
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops the console component.
|
||||
func (c *Component) Stop() error {
|
||||
c.r.Info().Msg("stopping console component")
|
||||
defer c.r.Info().Msg("console component stopped")
|
||||
c.t.Kill(nil)
|
||||
return c.t.Wait()
|
||||
}
|
||||
|
||||
// embedOrLiveFS returns a subset of the provided embedded filesystem,
|
||||
// except if the component is configured to use the live filesystem.
|
||||
// Then, it returns the provided tree.
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"akvorado/common/daemon"
|
||||
"akvorado/common/helpers"
|
||||
"akvorado/common/http"
|
||||
"akvorado/common/reporter"
|
||||
@@ -27,8 +26,7 @@ func TestProxy(t *testing.T) {
|
||||
_, err := New(r, Configuration{
|
||||
GrafanaURL: server.URL,
|
||||
}, Dependencies{
|
||||
HTTP: h,
|
||||
Daemon: daemon.NewMock(t),
|
||||
HTTP: h,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error:\n%+v", err)
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"akvorado/common/reporter"
|
||||
"bytes"
|
||||
"embed"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
//go:embed data/templates
|
||||
var embeddedTemplates embed.FS
|
||||
|
||||
// baseData is the data to pass for all templates.
|
||||
type templateBaseData struct {
|
||||
RootPath string
|
||||
CurrentPath string
|
||||
}
|
||||
|
||||
// loadTemplates reload the templates.
|
||||
func (c *Component) loadTemplates() error {
|
||||
mainTemplate, err := template.
|
||||
New("main").
|
||||
Option("missingkey=error").
|
||||
Funcs(sprig.FuncMap()).
|
||||
Parse(`{{define "main" }}{{ template "base" . }}{{ end }}`)
|
||||
if err != nil {
|
||||
c.r.Err(err).Msg("unable to create main template")
|
||||
return fmt.Errorf("unable to create main template: %w", err)
|
||||
}
|
||||
|
||||
layoutFiles := c.embedOrLiveFS(embeddedTemplates, "data/templates/layout")
|
||||
templateFiles := c.embedOrLiveFS(embeddedTemplates, "data/templates")
|
||||
compiled := make(map[string]*template.Template)
|
||||
entries, err := fs.ReadDir(templateFiles, ".")
|
||||
if err != nil {
|
||||
c.r.Err(err).Msg("unable to list template files")
|
||||
return fmt.Errorf("unable to list template files: %w", err)
|
||||
}
|
||||
for _, tpl := range entries {
|
||||
if tpl.IsDir() {
|
||||
continue
|
||||
}
|
||||
template, err := mainTemplate.Clone()
|
||||
if err != nil {
|
||||
c.r.Err(err).Msg("unable to clone main template")
|
||||
return fmt.Errorf("unable to clone main template: %w", err)
|
||||
}
|
||||
f, err := templateFiles.Open(tpl.Name())
|
||||
if err != nil {
|
||||
c.r.Err(err).Str("template", tpl.Name()).Msg("unable to open template")
|
||||
return fmt.Errorf("unable to open template %q: %w", tpl.Name(), err)
|
||||
}
|
||||
content, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
c.r.Err(err).Str("template", tpl.Name()).Msg("unable to read template")
|
||||
return fmt.Errorf("unable to read template %q: %w", tpl.Name(), err)
|
||||
}
|
||||
f.Close()
|
||||
template, err = template.Parse(string(content))
|
||||
if err != nil {
|
||||
c.r.Err(err).Str("template", tpl.Name()).Msg("unable to parse template")
|
||||
return fmt.Errorf("unable to parse template %q: %w", tpl.Name(), err)
|
||||
}
|
||||
template, err = template.ParseFS(layoutFiles, "*.html")
|
||||
if err != nil {
|
||||
c.r.Err(err).Msg("unable to parse layout templates")
|
||||
return fmt.Errorf("unable to parse layout templates: %w", err)
|
||||
}
|
||||
compiled[tpl.Name()] = template
|
||||
}
|
||||
c.templatesLock.Lock()
|
||||
c.templates = compiled
|
||||
c.templatesLock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// renderTemplate render the specified template
|
||||
func (c *Component) renderTemplate(w http.ResponseWriter, name string, data interface{}) {
|
||||
c.templatesLock.RLock()
|
||||
tmpl, ok := c.templates[name]
|
||||
c.templatesLock.RUnlock()
|
||||
if !ok {
|
||||
c.r.Error().Str("template", name).Msg("template not found")
|
||||
http.Error(w, fmt.Sprintf("No template %q found.", name), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
if err := tmpl.Execute(buf, data); err != nil {
|
||||
c.r.Err(err).Str("template", name).Msg("error while rendering template")
|
||||
http.Error(w, fmt.Sprintf("Error while rendering %q.", name), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
buf.WriteTo(w)
|
||||
}
|
||||
|
||||
// watchTemplates monitor changes in template directories and reload them
|
||||
func (c *Component) watchTemplates() error {
|
||||
if !c.config.ServeLiveFS {
|
||||
return nil
|
||||
}
|
||||
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
c.r.Err(err).Msg("cannot setup watcher for templates")
|
||||
return fmt.Errorf("cannot setup watcher: %w", err)
|
||||
}
|
||||
for _, dir := range []string{"templates", "templates/layout"} {
|
||||
_, base, _, _ := runtime.Caller(0)
|
||||
dir = filepath.Join(path.Dir(base), "data", dir)
|
||||
if err := watcher.Add(dir); err != nil {
|
||||
c.r.Err(err).Str("directory", dir).Msg("cannot watch template directory")
|
||||
return fmt.Errorf("cannot watch template directory %q: %w", dir, err)
|
||||
}
|
||||
}
|
||||
c.t.Go(func() error {
|
||||
defer watcher.Close()
|
||||
errLogger := c.r.Sample(reporter.BurstSampler(10*time.Second, 1))
|
||||
timer := time.NewTimer(100 * time.Millisecond)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-c.t.Dying():
|
||||
return nil
|
||||
case err := <-watcher.Errors:
|
||||
errLogger.Err(err).Msg("error from watcher")
|
||||
case event := <-watcher.Events:
|
||||
if event.Op&(fsnotify.Write|fsnotify.Create) == 0 {
|
||||
continue
|
||||
}
|
||||
timer.Stop()
|
||||
timer.Reset(500 * time.Millisecond)
|
||||
case <-timer.C:
|
||||
c.r.Info().Msg("reload templates")
|
||||
c.loadTemplates() // errors are ignored
|
||||
}
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"akvorado/common/daemon"
|
||||
"akvorado/common/http"
|
||||
"akvorado/common/reporter"
|
||||
)
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
for _, live := range []bool{false, true} {
|
||||
name := "livefs"
|
||||
if !live {
|
||||
name = "embeddedfs"
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
r := reporter.NewMock(t)
|
||||
c, err := New(r, Configuration{
|
||||
ServeLiveFS: live,
|
||||
}, Dependencies{
|
||||
HTTP: http.NewMock(t, r),
|
||||
Daemon: daemon.NewMock(t),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error:\n%+v", err)
|
||||
}
|
||||
if err := c.Start(); err != nil {
|
||||
t.Fatalf("Start() error:\n%+v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := c.Stop(); err != nil {
|
||||
t.Fatalf("Stop() error:\n%+v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c.renderTemplate(w, "dummy.html", templateBaseData{
|
||||
RootPath: ".",
|
||||
})
|
||||
|
||||
if w.Code != 200 {
|
||||
t.Errorf("renderTemplate() code was %d, expected 200", w.Code)
|
||||
}
|
||||
body := strings.TrimSpace(w.Body.String())
|
||||
if !strings.HasPrefix(body, "<!doctype html>") {
|
||||
t.Errorf("renderTemplate() body should contain <!doctype html>, got:\n%s",
|
||||
body)
|
||||
}
|
||||
|
||||
if live && !testing.Short() {
|
||||
// Wait for refresh of templates to happen.
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user