diff --git a/.gitignore b/.gitignore index 32330343..6e7fc754 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ assets/yarn-error.log assets/fonts result* cbits/*.cpp +pgdata/ +.vscode/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 74c0b651..48992751 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,13 @@ FROM gbogard/haskell-bullseye:8.10.7 # generate a working directory WORKDIR /flora-server -# install dependencies (pg_config & yarn) +# install dependencies (pg_config, postgresql-client, postrgresql-migrations & yarn) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - RUN curl -fsSL https://deb.nodesource.com/setup_17.x | bash - RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt update -RUN apt install -y nodejs yarn libpq-dev mcpp wget zsh tmux +RUN apt install -y nodejs yarn libpq-dev mcpp wget zsh tmux postgresql-client +RUN cabal install postgresql-migration # install soufflé RUN wget --content-disposition https://github.com/souffle-lang/souffle/releases/download/2.2/x86_64-ubuntu-2004-souffle-2.2-Linux.deb diff --git a/Makefile b/Makefile index 3cb6933b..f240cca3 100644 --- a/Makefile +++ b/Makefile @@ -64,9 +64,12 @@ style: ## Run the code formatters (stylish-haskell, cabal-fmt, nixfmt) nix-shell: ## Enter the Nix shell @nix-shell -docker-start: ## Start the container cluster +docker-build: ## Build and start the container cluster @docker-compose up -d --build +docker-start: ## Start the container cluster + @docker-compose up -d + docker-enter: ## Enter the docker environment docker-compose exec flora-server "zsh" diff --git a/README.md b/README.md index 1dd107e7..e3256a20 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,9 @@ A docker-based workflow is provided. The idea is to develop from within a contai and communicates with another container for the Postgres database. ```bash -# It's gonna take around 13 minutes the first time you build +# You need to build the container first. It's gonna take around 13 minutes the first time you build +$ make docker-build +# Start the container. $ make docker-start # Once the containers are running, you can enter the development environment and start hacking $ make docker-enter diff --git a/assets/css/app.css b/assets/css/app.css index 6cb51744..8e26de68 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -4,62 +4,38 @@ @layer base { a { - @apply text-link dark:text-link-dark + @apply text-link dark:text-brand-purple-light; } } -#darkmode-toggle:checked ~ label div.toggle-dot { - @apply translate-x-3; +@layer components { + .larger-container { + @apply max-w-7xl mx-auto px-2; + } + + .form-input { + @apply my-1 rounded-md p-2 text-gray-900 placeholder-gray-600 border-1 border-gray-500; + } + + .btn { + @apply rounded-md p-2 hover:bg-brand-purple-dark + } } #navbar-search-package-name { padding-left: 20px; } -.error-code{ +.error-code { --tw-bg-opacity: 1; color: hsl(270, 50%, 40%); } -.error-page-button{ +.error-page-button { --tw-bg-opacity: 1; background-color: hsl(270, 50%, 40%); } -#user-menu-container { - position: relative; -} - -#user-menu-nav{ - z-index: 1; - top: 100%; - width: max-content; - max-width: 14rem; -} - -.user-menu-element { - padding: 10px 15px; -} - -.user-menu-element a, -.user-menu-element a:visited { - color: inherit; - display: block; -} - -.user-menu-element a:hover, -.user-menu-element a:active, -.user-menu-element a:focus { - text-decoration: underline; -} - -.user-menu-divider { - display: block; - height: 1px; - background-color: currentColor; - opacity: .4; -} - ul[class="bullets"] { li { list-style-type: disc; @@ -67,7 +43,7 @@ ul[class="bullets"] { } } -div[class="bullets"]{ +div[class="bullets"] { ul { li { list-style-type: disc; @@ -77,72 +53,37 @@ div[class="bullets"]{ } .navbar-element { - color: hsl(0, 0%, 100%); + color: hsl(0, 0%, 100%); } -.navbar-element:hover{ - --tw-text-opacity: 1; - color: hsl(254.3,95%,76.7%); +.navbar-element:hover { + --tw-text-opacity: 1; + color: hsl(254.3, 95%, 76.7%); } /* Dark mode-specific rules */ -.dark{ - .navbar{ - background-color: hsl(0.65, 0.14%, 0.24%); - } - - .navbar-element:hover{ - --tw-text-opacity: 1; - color: hsl(254.3,95%,76.7%); - } +.dark { - .social-button:hover{ + .social-button:hover { --tw-text-opacity: 1; - color: hsl(254.3,95%,76.7%); + color: hsl(254.3, 95%, 76.7%); } - .package-body{ - a:hover{ - --tw-text-opacity: 1; - color: hsl(254.3,95%,76.7%); - } - } +} - .navbar-right{ - .active{ - --tw-border-opacity: 1; - border-bottom-color: hsl(270, 50%, 40%); - border-bottom-width: 2px; - } - } +.divider { + padding-bottom: 1em; + margin-bottom: 0.66em; + border-bottom: 1px solid hsl(0, 0%, 80%); +} - .categories{ - a { - color: unset; - } - } - .packages-list{ - a { - color: unset; - } - } - .packages-list-item{ - a { - display: block; - padding-top: 1em; - padding-bottom: 1em; - padding-left: 0.75em; - } - a:hover{ - background-color: hsl(234, 17%, 24%); - border-radius: 5px; - } - } +.card { + @apply block bg-white dark:bg-background-darker rounded-lg shadow-lg py-4 px-8; } /* Large display rules */ @media (min-width: 1024px) { - .container{ + .container { width: auto; max-width: 1100px; padding-right: 15px; @@ -151,21 +92,12 @@ div[class="bullets"]{ margin-left: auto; } - .categories{ - width: auto; - max-width: 1536px; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; - } - - .category-card{ + .card { --tw-shadow-color: rgb(102 51 153 / 0.25); --tw-shadow: var(--tw-shadow-colored); } - .about-page{ + .about-page { width: auto; max-width: 1000px; padding-right: 15px; @@ -174,56 +106,26 @@ div[class="bullets"]{ margin-left: auto; } - body{ - height: 100%; - } - - html{ - height: 100%; - } - - .navbar{ + .navbar { margin-bottom: 20rem; font-size: 1.5rem; line-height: 2rem; margin-bottom: 4rem; } - .headline{ + .headline { margin-bottom: 5px; } - .divider{ - padding-bottom: 1em; - margin-bottom: .66em; - border-bottom: 1px solid hsl(0, 0%, 80%); - } - .version{ + + .version { font-size: 1.3rem; line-height: 1.3rem; padding-left: 4px; } - .package-body-section{ - font-weight: 700; - display: inline-block; + .dependency { white-space: nowrap; } - - .dependency{ - white-space: nowrap; - } - - .package-left-column{ - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); - } - - .package-right-column{ - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); - } } diff --git a/assets/icons/moon.svg b/assets/icons/moon.svg new file mode 100644 index 00000000..d415cd12 --- /dev/null +++ b/assets/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/search.svg b/assets/icons/search.svg new file mode 100644 index 00000000..071bc5d1 --- /dev/null +++ b/assets/icons/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/sun.svg b/assets/icons/sun.svg new file mode 100644 index 00000000..d5ec5598 --- /dev/null +++ b/assets/icons/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/js/app.js b/assets/js/app.js index 25b699e5..001220e9 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,20 +1,3 @@ -import Alpine from 'alpinejs' -window.Alpine = Alpine -Alpine.start() - -const checkbox = document.querySelector("#darkmode-toggle"); -const html = document.querySelector("html"); - -const toggleDarkMode = () => { - if (checkbox.checked) { - html.classList.add("dark"); - localStorage.theme = "dark"; - console.log("[+] Enabling and saving dark mode preference"); - } else { - html.classList.remove("dark"); - localStorage.theme = "light"; - console.log("[+] Enabling and saving light mode preference"); - } -} - -checkbox.addEventListener("click", toggleDarkMode); +import Alpine from "alpinejs"; +window.Alpine = Alpine; +Alpine.start(); diff --git a/assets/package.json b/assets/package.json index f29facde..d7d383e9 100644 --- a/assets/package.json +++ b/assets/package.json @@ -6,6 +6,7 @@ "alpinejs": "^3.9.6", "autoprefixer": "^10.4.0", "concurrently": "^6.4.0", + "cpx": "^1.5.0", "cssnano": "^5.0.10", "esbuild": "^0.13.13", "esbuild-copy-static-files": "^0.1.0", @@ -16,11 +17,13 @@ "tailwindcss": "^3.0.0" }, "scripts": { - "watch": "concurrently \"yarn:watch-css\" \"yarn:watch-js\"", - "build": "concurrently \"yarn:build-css\" \"yarn:build-js\"", + "watch": "concurrently \"yarn:watch-css\" \"yarn:watch-js\" \"yarn:watch-static-files\"", + "build": "concurrently \"yarn:build-css\" \"yarn:build-js\" \"yarn:copy-static-files\"", "watch-js": "node esbuild.config.js", "build-js": "esbuild js/app.js --asset-names=[name]-[hash].js --bundle --minify --target=es2016 --outdir=../static/js/", "watch-css": "postcss css/app.css -o ../static/css/app.css -w", - "build-css": "NODE_BUILD=prod postcss css/app.css -o ../static/css/app.css" + "build-css": "NODE_BUILD=prod postcss css/app.css -o ../static/css/app.css", + "copy-static-files": "cpx **/*.{svg,png,jpg} ../static", + "watch-static-files": "cpx **/*.{svg,png,jpg} ../static -w" } } diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index 63663813..c02c4d58 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,14 +12,18 @@ module.exports = { colors: { "background": { "dark": "#25282a", + "darker": "#1D2021", "dark-focused": "#3a3d3f", "DEFAULT": "#f3f4f6", }, "brand-purple": { "DEFAULT": "#4e315e", + "dark": "#352140", + "light": "#EFC3F5" }, "navbar": { - "dark": "#1D2021" + "dark": "#1D2021", + "darker": "#16191a" }, "link": { "dark": "#4dabf7", diff --git a/assets/webfonts/fa-brands-400.eot b/assets/webfonts/fa-brands-400.eot deleted file mode 100644 index cba6c6cc..00000000 Binary files a/assets/webfonts/fa-brands-400.eot and /dev/null differ diff --git a/assets/webfonts/fa-brands-400.svg b/assets/webfonts/fa-brands-400.svg deleted file mode 100644 index b9881a43..00000000 --- a/assets/webfonts/fa-brands-400.svg +++ /dev/null @@ -1,3717 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/webfonts/fa-brands-400.ttf b/assets/webfonts/fa-brands-400.ttf deleted file mode 100644 index 8d75dedd..00000000 Binary files a/assets/webfonts/fa-brands-400.ttf and /dev/null differ diff --git a/assets/webfonts/fa-brands-400.woff b/assets/webfonts/fa-brands-400.woff deleted file mode 100644 index 3375bef0..00000000 Binary files a/assets/webfonts/fa-brands-400.woff and /dev/null differ diff --git a/assets/webfonts/fa-brands-400.woff2 b/assets/webfonts/fa-brands-400.woff2 deleted file mode 100644 index 402f81c0..00000000 Binary files a/assets/webfonts/fa-brands-400.woff2 and /dev/null differ diff --git a/assets/webfonts/fa-regular-400.eot b/assets/webfonts/fa-regular-400.eot deleted file mode 100644 index a4e59893..00000000 Binary files a/assets/webfonts/fa-regular-400.eot and /dev/null differ diff --git a/assets/webfonts/fa-regular-400.svg b/assets/webfonts/fa-regular-400.svg deleted file mode 100644 index 463af27c..00000000 --- a/assets/webfonts/fa-regular-400.svg +++ /dev/null @@ -1,801 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/webfonts/fa-regular-400.ttf b/assets/webfonts/fa-regular-400.ttf deleted file mode 100644 index 7157aafb..00000000 Binary files a/assets/webfonts/fa-regular-400.ttf and /dev/null differ diff --git a/assets/webfonts/fa-regular-400.woff b/assets/webfonts/fa-regular-400.woff deleted file mode 100644 index ad077c6b..00000000 Binary files a/assets/webfonts/fa-regular-400.woff and /dev/null differ diff --git a/assets/webfonts/fa-regular-400.woff2 b/assets/webfonts/fa-regular-400.woff2 deleted file mode 100644 index 56328948..00000000 Binary files a/assets/webfonts/fa-regular-400.woff2 and /dev/null differ diff --git a/assets/webfonts/fa-solid-900.eot b/assets/webfonts/fa-solid-900.eot deleted file mode 100644 index e9941719..00000000 Binary files a/assets/webfonts/fa-solid-900.eot and /dev/null differ diff --git a/assets/webfonts/fa-solid-900.svg b/assets/webfonts/fa-solid-900.svg deleted file mode 100644 index 00296e95..00000000 --- a/assets/webfonts/fa-solid-900.svg +++ /dev/null @@ -1,5034 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/webfonts/fa-solid-900.ttf b/assets/webfonts/fa-solid-900.ttf deleted file mode 100644 index 25abf389..00000000 Binary files a/assets/webfonts/fa-solid-900.ttf and /dev/null differ diff --git a/assets/webfonts/fa-solid-900.woff b/assets/webfonts/fa-solid-900.woff deleted file mode 100644 index 23ee6634..00000000 Binary files a/assets/webfonts/fa-solid-900.woff and /dev/null differ diff --git a/assets/webfonts/fa-solid-900.woff2 b/assets/webfonts/fa-solid-900.woff2 deleted file mode 100644 index 2217164f..00000000 Binary files a/assets/webfonts/fa-solid-900.woff2 and /dev/null differ diff --git a/assets/yarn.lock b/assets/yarn.lock index 3983b24b..142786d4 100644 --- a/assets/yarn.lock +++ b/assets/yarn.lock @@ -130,6 +130,14 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -143,12 +151,19 @@ arg@^5.0.1: resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= -arr-flatten@^1.1.0: +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== @@ -163,6 +178,11 @@ array-union@^3.0.1: resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -173,6 +193,11 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= +async-each@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -190,6 +215,14 @@ autoprefixer@^10.4.0: picocolors "^1.0.0" postcss-value-parser "^4.2.0" +babel-runtime@^6.9.2: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -208,11 +241,23 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + 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== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -226,6 +271,15 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -317,6 +371,22 @@ chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chokidar@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + chokidar@^3.3.0, chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -427,6 +497,16 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +core-js@^2.4.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cosmiconfig@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" @@ -438,6 +518,23 @@ cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cpx@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/cpx/-/cpx-1.5.0.tgz#185be018511d87270dedccc293171e37655ab88f" + integrity sha1-GFvgGFEdhycN7czCkxceN2VauI8= + dependencies: + babel-runtime "^6.9.2" + chokidar "^1.6.0" + duplexer "^0.1.1" + glob "^7.0.5" + glob2base "^0.0.12" + minimatch "^3.0.2" + mkdirp "^0.5.1" + resolve "^1.1.7" + safe-buffer "^5.0.1" + shell-quote "^1.6.1" + subarg "^1.0.0" + css-declaration-sorter@^6.0.3: version "6.1.4" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" @@ -635,6 +732,11 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +duplexer@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + electron-to-chromium@^1.4.17: version "1.4.53" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.53.tgz#5d80a91c399b44952ef485857fb5b9d4387d2e60" @@ -780,6 +882,13 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -793,6 +902,13 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -808,6 +924,13 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -840,6 +963,27 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -857,11 +1001,23 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -for-in@^1.0.2: +find-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" + integrity sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ= + +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + fraction.js@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" @@ -888,6 +1044,14 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@^1.0.0: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -913,6 +1077,21 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + 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" @@ -927,7 +1106,14 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.7: +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + integrity sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY= + dependencies: + find-index "^0.1.1" + +glob@^7.0.5, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -951,6 +1137,11 @@ globby@^12.0.0: merge2 "^1.4.1" slash "^4.0.0" +graceful-fs@^4.1.11: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" @@ -1025,7 +1216,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1049,6 +1240,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + 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" @@ -1100,6 +1298,18 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -1112,6 +1322,11 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1122,6 +1337,13 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + 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" @@ -1129,6 +1351,13 @@ is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -1136,6 +1365,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1148,12 +1382,22 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -isarray@1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -1250,6 +1494,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -1260,7 +1509,26 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^3.0.3: +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.0.3, micromatch@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -1287,6 +1555,13 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +minimatch@^3.0.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -1294,7 +1569,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -1319,6 +1594,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +nan@^2.12.1: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + nanoid@^3.1.30: version "3.2.0" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" @@ -1346,6 +1626,13 @@ node-releases@^2.0.1: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + 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" @@ -1389,6 +1676,14 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -1410,6 +1705,16 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.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" @@ -1765,11 +2070,21 @@ postcss@^8.3.11, postcss@^8.3.5: picocolors "^1.0.0" source-map-js "^1.0.1" +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + purgecss@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.1.3.tgz#683f6a133c8c4de7aa82fe2746d1393b214918f7" @@ -1790,6 +2105,15 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -1797,6 +2121,28 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +readable-stream@^2.0.2: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -1804,6 +2150,18 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -1812,12 +2170,17 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.6.1: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -1870,6 +2233,16 @@ rxjs@^6.6.3: dependencies: tslib "^1.9.0" +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -1887,6 +2260,11 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +shell-quote@^1.6.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + slash@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" @@ -1987,6 +2365,13 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2002,6 +2387,13 @@ stylehacks@^5.0.2: browserslist "^4.16.6" postcss-selector-parser "^6.0.4" +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= + dependencies: + minimist "^1.1.0" + supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2152,7 +2544,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.2: +util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= diff --git a/scripts/.zshrc b/scripts/.zshrc index 033fe669..ebde3c5a 100644 --- a/scripts/.zshrc +++ b/scripts/.zshrc @@ -1,4 +1,5 @@ export ZSH="$HOME/.oh-my-zsh" +export LANG=C.UTF-8 ZSH_THEME="robbyrussell" plugins=(git) @@ -10,4 +11,4 @@ export FLORA_PG_URI="postgresql://${FLORA_DB_USER}:${FLORA_DB_PASSWORD}@${FLORA_ export FLORA_PG_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD}" export FLORA_HTTP_PORT=8084 -cat /etc/motd \ No newline at end of file +cat /etc/motd diff --git a/scripts/shell-welcome.txt b/scripts/shell-welcome.txt index c75c15c6..b53ad35a 100644 --- a/scripts/shell-welcome.txt +++ b/scripts/shell-welcome.txt @@ -7,6 +7,6 @@ To start the server: 'make watch-server' -To start the assets pipeline: 'make assets-watch' +To start the assets pipeline: 'make watch-assets' Happy hacking! diff --git a/src/FloraWeb/Server/Pages/Packages.hs b/src/FloraWeb/Server/Pages/Packages.hs index 1d561f31..2fe907de 100644 --- a/src/FloraWeb/Server/Pages/Packages.hs +++ b/src/FloraWeb/Server/Pages/Packages.hs @@ -52,9 +52,7 @@ indexHandler = do session <- getSession templateDefaults <- fromSession session defaultTemplateEnv results <- Search.listAllPackages - let (templateEnv :: TemplateEnv) = - templateDefaults & #displayNavbarSearch .~ False - render templateEnv $ Search.showAllPackages results + render templateDefaults $ Search.showAllPackages results showHandler :: Text -> Text -> FloraPageM (Html ()) showHandler namespaceText packageNameText = do diff --git a/src/FloraWeb/Server/Pages/Search.hs b/src/FloraWeb/Server/Pages/Search.hs index c08e9bd8..fc57d6a0 100644 --- a/src/FloraWeb/Server/Pages/Search.hs +++ b/src/FloraWeb/Server/Pages/Search.hs @@ -29,4 +29,4 @@ searchHandler (Just searchString) = do session <- getSession templateEnv <- fromSession session defaultTemplateEnv results <- Search.searchPackageByName searchString - render templateEnv $ Search.showResults searchString results + render templateEnv $ Search.showResults (Just searchString) results diff --git a/src/FloraWeb/Templates/Layout/App.hs b/src/FloraWeb/Templates/Layout/App.hs index 6bfde9de..c1614305 100644 --- a/src/FloraWeb/Templates/Layout/App.hs +++ b/src/FloraWeb/Templates/Layout/App.hs @@ -9,6 +9,10 @@ where import Control.Monad.Reader import Data.Text +import Data.Text.Display +import Flora.Model.PersistentSession +import Flora.Model.User +import FloraWeb.Templates.Types import Lucid import Lucid.Alpine import Lucid.Base (makeAttribute) @@ -16,50 +20,41 @@ import Lucid.Svg (clip_rule_, d_, fill_, fill_rule_, path_, viewBox_) import Optics.Core import PyF -import Data.Text.Display -import Flora.Model.PersistentSession -import Flora.Model.User -import FloraWeb.Templates.Types - header :: FloraHTML header = do TemplateEnv{title} <- ask doctype_ - html_ [lang_ "en", class_ "no-js dark"] $ do - head_ $ do - meta_ [charset_ "UTF-8"] - meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1"] - title_ (text title) - - script_ [type_ "module"] $ do - toHtmlRaw @Text - [str| + html_ + [ lang_ "en" + , class_ "no-js" + , xBind_ "class" "darkMode ? 'dark' : ''" + , xData_ "{ darkMode: localStorage.getItem('darkMode') !== 'false' }" + , xInit_ "$watch('darkMode', val => localStorage.setItem('darkMode', val))" + ] + $ do + head_ $ do + meta_ [charset_ "UTF-8"] + meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1"] + title_ (text title) + + script_ [type_ "module"] $ do + toHtmlRaw @Text + [str| document.documentElement.classList.remove('no-js'); document.documentElement.classList.add('js'); - const html = document.querySelector('html'); - const checkbox = document.querySelector('#darkmode-toggle'); - if (localStorage.theme === 'dark' - || (!('theme' in localStorage) - && window.matchMedia('(prefers-color-scheme: dark)').matches)) {{ - html.classList.add('dark'); - checkbox.checked = true - }} else {{ - html.classList.remove('dark'); - checkbox.checked = false - }} |] - script_ [src_ "/static/js/app.js", type_ "module", defer_ ""] ("" :: Text) + script_ [src_ "/static/js/app.js", type_ "module", defer_ ""] ("" :: Text) - link_ [rel_ "stylesheet", href_ "/static/css/app.css"] - meta_ [name_ "description", content_ "A package repository for the Haskell ecosystem"] - ogTags - theme - link_ [rel_ "icon", href_ "/static/favicon.svg", type_ "image/svg+xml"] - -- link_ [rel_ "canonical", href_ $ getCanonicalURL assigns] - meta_ [name_ "twitter:dnt", content_ "on"] + link_ [rel_ "stylesheet", href_ "/static/css/app.css"] + meta_ [name_ "description", content_ "A package repository for the Haskell ecosystem"] + ogTags + theme + link_ [rel_ "icon", href_ "/static/favicon.svg", type_ "image/svg+xml"] + -- link_ [rel_ "canonical", href_ $ getCanonicalURL assigns] + meta_ [name_ "twitter:dnt", content_ "on"] - body_ [class_ "bg-background dark:bg-background-dark dark:text-gray-100"] $ do - navBar + body_ [class_ "bg-background dark:bg-background-dark dark:text-gray-100"] $ do + navBar ogTags :: FloraHTML ogTags = do @@ -79,24 +74,52 @@ theme = do meta_ [name_ "theme-color", content_ "#000", media_ "(prefers-color-scheme: dark)"] meta_ [name_ "theme-color", content_ "#FFF", media_ "(prefers-color-scheme: light)"] +brand :: FloraHTML +brand = do + TemplateEnv{title, mobileTitle} <- ask + let link = a_ [href_ "/", id_ "brand", class_ "font-bold text-white dark:text-gray-100"] + let containerBaseClasses = "flex items-center border-b-4 border-brand-purple-light dark:border-brand-purple flex-shrink-0 h-16" + div_ [class_ $ containerBaseClasses <> " hidden md:flex"] $ link (text title) + div_ [class_ $ containerBaseClasses <> " md:hidden", xOn_ "click.prevent" "menuOpen = !menuOpen"] $ link (text mobileTitle) + +navBarLink :: Text -> Text -> Text -> Bool -> FloraHTML +navBarLink additionalClasses href label isActive' = + let baseClasses = "font-bold inline-flex items-center py-3 mx-4 text-white dark:text-gray-100 " + in a_ [href_ href, class_ (baseClasses <> additionalClasses <> " " <> isActive isActive')] (text label) + +navBarLink' :: Text -> Text -> Bool -> FloraHTML +navBarLink' = navBarLink "" + navBar :: FloraHTML navBar = do - TemplateEnv{title} <- ask ActiveElements{aboutNav, packagesNav} <- asks activeElements - nav_ [class_ "border-b dark:border-transparent bg-brand-purple dark:bg-navbar-dark mb-3"] $ do + TemplateEnv{title} <- ask + let menuClasses = + "md:flex flex md:items-center " + <> "bg-brand-purple-dark md:bg-brand-purple dark:bg-navbar-darker md:dark:bg-navbar-dark " + <> "flex flex-col md:flex-row absolute md:relative top-[100%] left-0 w-full md:w-auto md:top-0" + nav_ [class_ "sticky top-0 left-0 border-b dark:border-transparent bg-brand-purple dark:bg-navbar-dark mb-3 z-10", xData_ "{menuOpen: false}"] $ do div_ [id_ "navbar-content", class_ "max-w-9xl mx-auto px-4 sm:px-6 lg:px-8"] $ do - div_ [class_ "flex justify-between h-16 "] $ do - div_ [class_ "flex-shrink-0 flex "] $ do - div_ [class_ "flex-shrink-0 border-b-2 border-b-brand-purple py-2 px-1 pt-1 mx-7 text-white-200 items-center"] $ - a_ [href_ "/", class_ "navbar-element flex-shrink-0 py-2 inline-flex items-center font-bold text-white-200 dark:text-gray-100"] (text title) + div_ [class_ "md:flex md:justify-between h-16 "] $ do + div_ [id_ "navbar-left", class_ "flex flex-shrink-0"] $ do + brand navbarSearch - let elementClass = "font-bold navbar-element py-2 inline-flex items-center px-1 pt-1 mx-7 text-white-200 dark:text-gray-100" - div_ [id_ "navbar-right", class_ "hidden sm:flex justify-end"] $ do - a_ [href_ "/about", class_ (elementClass <> isActive aboutNav)] "About Flora" - a_ [href_ "/categories", class_ (elementClass <> isActive packagesNav)] "Categories" - a_ [href_ "/packages", class_ (elementClass <> isActive packagesNav)] "Packages" - userDropdown elementClass + div_ [id_ "navbar-right", class_ menuClasses, xBind_ "class" "!menuOpen ? 'hidden' : ''"] $ do + navBarLink "md:hidden " "/" title False + navBarLink' "/about" "About Flora" aboutNav + navBarLink' "/categories" "Categories" packagesNav + navBarLink' "/packages" "Packages" packagesNav + navBarLink' "#" "Guides" False + userMenu + darkModeToggle + +userMenu :: FloraHTML +userMenu = do + TemplateEnv{mUser, sessionId} <- ask + getUsernameOrLogin mUser + adminLink mUser + logOff mUser sessionId navbarSearch :: FloraHTML navbarSearch = do @@ -114,25 +137,12 @@ navbarSearch = do ] else pure mempty -userDropdown :: Text -> FloraHTML -userDropdown elementClass = do - TemplateEnv{mUser, sessionId} <- ask - div_ [id_ "user-menu-container", xData_ "{ userMenu: false }", xOn_ "click.outside" "userMenu = false", xOn_ "keydown.escape" "userMenu = false", class_ "flex"] $ do - button_ [xOn_ "click" "userMenu = !userMenu", xBind_ "aria-expanded" "userMenu ? 'true' : 'false'", id_ "user-menu-btn", class_ elementClass] "Menu" - nav_ [xShow_ "userMenu", id_ "user-menu-nav", class_ "bg-background dark:bg-background-dark rounded-md absolute right-0 border-2 border-brand-purple"] $ - ul_ [] $ do - li_ [class_ "user-menu-element"] $ getUsernameOrLogin mUser - li_ [class_ "user-menu-element"] $ a_ [href_ "#"] "Guides" - adminLink mUser - logOff mUser sessionId - li_ [class_ "user-menu-divider", role_ "separator"] "" - li_ [class_ "user-menu-element"] darkModeToggle - logOff :: Maybe User -> PersistentSessionId -> FloraHTML logOff Nothing _ = "" -logOff (Just _) sessionId = li_ [class_ "user-menu-element"] $ +logOff (Just _) sessionId = form_ [action_ ("/sessions/delete/" <> display sessionId), method_ "post", id_ "logoff"] $ do - button_ [type_ "submit"] "Sign out" + let btnClasses = "font-bold inline-flex items-center py-3 mx-4 text-white dark:text-gray-100 " + button_ [type_ "submit", class_ btnClasses] "Sign out" adminLink :: Maybe User -> FloraHTML adminLink (Just user) | user ^. #userFlags ^. #isAdmin = li_ [class_ "user-menu-element"] $ a_ [href_ "/admin"] "Admin Dashboard" @@ -140,14 +150,16 @@ adminLink _ = "" darkModeToggle :: FloraHTML darkModeToggle = do - div_ [class_ "flex justify-end items-center space-x-2"] $ do - span_ [class_ "text-sm text-gray-600 dark:text-gray-100"] "Light" - div_ [class_ ""] $ do - input_ [type_ "checkbox", name_ "", id_ "darkmode-toggle", class_ "hidden", checked_] - label_ [for_ "darkmode-toggle", class_ "cursor-pointer"] $ - div_ [class_ "w-9 h-5 flex items-center bg-gray-600 dark:bg-gray-600 rounded-full p-1"] $ do - div_ [class_ "toggle-dot w-4 h-4 bg-white rounded-full bg-white shadow-md transform duration-200 ease-in-out"] "" - span_ [class_ "text-sm text-gray-600 dark:text-gray-100"] "Dark" + let lightModeContent = do + img_ [src_ "/static/icons/moon.svg", class_ "h-6 w-6 mr-2"] + "Dark Mode" + let darkModeContent = do + img_ [src_ "/static/icons/sun.svg", class_ "h-6 w-6 mr-2 invert"] + "Light Mode" + let buttonBaseClasses = "p-2 m-4 md:m-0 rounded-md inline-flex items-center bg-slate-200 dark:bg-brand-purple" + button_ [xOn_ "click" "darkMode = !darkMode; menuOpen = false", class_ $ "hidden dark:inline-flex " <> buttonBaseClasses] darkModeContent + button_ [xOn_ "click" "darkMode = !darkMode; menuOpen = false", class_ $ "dark:hidden " <> buttonBaseClasses] lightModeContent + input_ [type_ "checkbox", name_ "", id_ "darkmode-toggle", class_ "hidden", xModel_ [] "darkMode"] footer :: FloraHTML footer = @@ -178,8 +190,8 @@ text :: Text -> FloraHTML text = toHtml getUsernameOrLogin :: Maybe User -> FloraHTML -getUsernameOrLogin Nothing = a_ [href_ "/sessions/new"] "Login/Signup" -getUsernameOrLogin _ = a_ [href_ "#"] "Profile" +getUsernameOrLogin Nothing = navBarLink' "/sessions/new" "Login/Signup" False +getUsernameOrLogin _ = navBarLink' "#" "Profile" False isActive :: Bool -> Text isActive True = " active" diff --git a/src/FloraWeb/Templates/Packages/Dependencies.hs b/src/FloraWeb/Templates/Packages/Dependencies.hs index 2611da69..dc2b17b9 100644 --- a/src/FloraWeb/Templates/Packages/Dependencies.hs +++ b/src/FloraWeb/Templates/Packages/Dependencies.hs @@ -6,13 +6,13 @@ import Data.Vector (Vector) import qualified Data.Vector as Vector import Flora.Model.Package (Namespace, PackageName) import FloraWeb.Templates (FloraHTML) -import FloraWeb.Templates.Packages.Listing (presentationHeader, prettyPackageName) +import FloraWeb.Templates.Packages.Listing (prettyPackageName, searchResultsAside) import Lucid showDependencies :: Text -> Vector (Namespace, PackageName, Text, Text) -> FloraHTML showDependencies searchString packagesInfo = do div_ [class_ "container dark:text-gray-100 text-black"] $ do - presentationHeader searchString (fromIntegral $ Vector.length packagesInfo) + searchResultsAside (Just searchString) (fromIntegral $ Vector.length packagesInfo) packageListing packagesInfo packageListing :: Vector (Namespace, PackageName, Text, Text) -> FloraHTML diff --git a/src/FloraWeb/Templates/Packages/Dependents.hs b/src/FloraWeb/Templates/Packages/Dependents.hs index a6ce6107..6aea57f2 100644 --- a/src/FloraWeb/Templates/Packages/Dependents.hs +++ b/src/FloraWeb/Templates/Packages/Dependents.hs @@ -12,5 +12,5 @@ import Lucid showDependents :: Text -> Vector (Namespace, PackageName, Text, Version) -> FloraHTML showDependents searchString packagesInfo = do div_ [class_ "container dark:text-gray-100 text-black"] $ do - presentationHeader searchString (fromIntegral $ Vector.length packagesInfo) + searchResultsAside (Just searchString) (fromIntegral $ Vector.length packagesInfo) packageListing packagesInfo diff --git a/src/FloraWeb/Templates/Packages/Listing.hs b/src/FloraWeb/Templates/Packages/Listing.hs index 5f041c9e..1408f7a4 100644 --- a/src/FloraWeb/Templates/Packages/Listing.hs +++ b/src/FloraWeb/Templates/Packages/Listing.hs @@ -11,24 +11,26 @@ import Flora.Model.Package import Flora.Model.Release.Orphans () import FloraWeb.Templates (FloraHTML) -presentationHeader :: Text -> Word -> FloraHTML -presentationHeader searchString numberOfPackages = do - div_ [class_ "divider"] $ do - div_ [class_ "px-4 py-5 sm:px-6 sm:py-24 lg:py-4 lg:px-8"] $ - h2_ [class_ "text-center text-2xl tracking-tight sm:text-2xl lg:text-5xl"] $ do - span_ [class_ "headline"] $ toHtml searchString - toHtmlRaw @Text " " - span_ [class_ "dark:text-gray-200 version"] $ toHtml $ display numberOfPackages <> " packages" +searchResultsAside :: Maybe Text -> Word -> FloraHTML +searchResultsAside mSearchString numberOfPackages = do + div_ [class_ "px-4 py-3 sm:px-6 bg-white shadow-sm dark:bg-slate-600 rounded-md flex items-center"] $ do + case mSearchString of + Just searchString -> do + img_ [src_ "/static/icons/search.svg", class_ "h-6 w-6 mr-2 dark:invert"] + div_ [] $ do + h5_ [] $ toHtml searchString + strong_ [class_ "dark:text-gray-200"] $ toHtml $ display numberOfPackages <> " packages" + Nothing -> span_ [class_ "dark:text-gray-200"] $ toHtml $ display numberOfPackages <> " packages" showPackage :: (Namespace, PackageName, Text, Version) -> FloraHTML showPackage (namespace, name, synopsis, version) = do - a_ [href_ ("/packages/@" <> display namespace <> "/" <> display name)] $ do - div_ [class_ "text-slate-300 hover:text-slate-200"] $ do - p_ - [class_ "package-name inline text-link dark:text-link-dark"] - (toHtml $ prettyPackageName namespace name) - p_ [class_ "synopsis inline ml-3"] (toHtml synopsis) - div_ [class_ "text-slate-300 text-sm"] $ "v" <> toHtml (display version) + let href = href_ ("/packages/@" <> display namespace <> "/" <> display name) + let classes = "card text-inherit my-4 md:my-6" + a_ [href, class_ classes] $ do + h3_ [class_ "text-brand-purple dark:text-brand-purple-light"] $ do + strong_ [] . toHtml $ prettyPackageName namespace name + small_ [class_ "mx-2"] $ "v" <> (toHtml . display $ version) + p_ [class_ "text-neutral-900 dark:text-gray-200"] $ toHtml synopsis prettyPackageName :: Namespace -> PackageName -> Text prettyPackageName namespace name = "@" <> display namespace <> "/" <> display name @@ -37,8 +39,5 @@ packageListing :: Vector (Namespace, PackageName, Text, Version) -> FloraHTML packageListing packages = do ul_ [class_ "packages-list"] $ do Vector.forM_ packages $ \pInfo -> do - li_ [class_ "packages-list-item xl:text-xl dark:text-gray-200"] $ + li_ [] $ showPackage pInfo - -getPackageInfo :: Package -> Version -> (Namespace, PackageName, Text, Version) -getPackageInfo Package{namespace, name, synopsis} version = (namespace, name, synopsis, version) diff --git a/src/FloraWeb/Templates/Pages/Categories/Index.hs b/src/FloraWeb/Templates/Pages/Categories/Index.hs index f32feb3e..c8d8bf4c 100644 --- a/src/FloraWeb/Templates/Pages/Categories/Index.hs +++ b/src/FloraWeb/Templates/Pages/Categories/Index.hs @@ -2,7 +2,6 @@ module FloraWeb.Templates.Pages.Categories.Index where import Data.Vector (Vector) import qualified Data.Vector as V - import Flora.Model.Category (Category (..)) import FloraWeb.Templates (FloraHTML) import Lucid @@ -10,14 +9,11 @@ import Lucid index :: Vector Category -> FloraHTML index categories = do h1_ [class_ "text-center text-2xl tracking-tight sm:text-2xl lg:text-5xl"] "Categories" - div_ [class_ "categories grid grid-cols-3 gap-3 mt-8 mb-8"] $ do + div_ [class_ "larger-container grid grid-cols-1 md:grid-cols-3 gap-4 md:gap-8 my-12"] $ do V.forM_ categories categoryCard categoryCard :: Category -> FloraHTML categoryCard Category{name, slug, synopsis} = do - a_ [class_ "category-name", href_ ("/categories/" <> slug)] $ - div_ [class_ "category-card max-w-md py-4 px-8 shadow-lg rounded-lg my-16"] $ do - div_ $ do - h2_ [class_ "font-semibold"] $ - p_ [class_ "category-name"] (toHtml name) - p_ [class_ "mt-2 text-gray-200"] $ toHtml synopsis + a_ [class_ "card", href_ ("/categories/" <> slug)] $ do + h2_ [class_ "font-semibold text-brand-purple dark:text-brand-purple-light"] (toHtml name) + p_ [class_ "mt-2 text-neutral-900 dark:text-gray-200"] $ toHtml synopsis diff --git a/src/FloraWeb/Templates/Pages/Packages.hs b/src/FloraWeb/Templates/Pages/Packages.hs index f5e71369..5ff3d68b 100644 --- a/src/FloraWeb/Templates/Pages/Packages.hs +++ b/src/FloraWeb/Templates/Pages/Packages.hs @@ -43,7 +43,7 @@ showPackage :: Vector Category -> FloraHTML showPackage latestRelease package@Package{namespace, name, synopsis} dependents numberOfDependents dependencies numberOfDependencies categories = do - div_ [class_ "container dark:text-gray-100 text-black"] $ do + div_ [class_ "larger-container"] $ do presentationHeader latestRelease namespace name synopsis packageBody package latestRelease dependencies numberOfDependencies dependents numberOfDependents categories @@ -60,13 +60,12 @@ presentationHeader release namespace name synopsis = do packageBody :: Package -> Release -> Vector (Namespace, PackageName, Text) -> Word -> Vector Package -> Word -> Vector Category -> FloraHTML packageBody Package{namespace, name = packageName, metadata} latestRelease dependencies numberOfDependencies dependents numberOfDependents categories = div_ [class_ "package-body"] $ do - div_ [class_ "grid grid-cols-4 gap-2 mt-8"] $ do + div_ [class_ "grid md:grid-cols-2 gap-2 mt-8"] $ do div_ [class_ "package-left-column"] $ do div_ [class_ "grid-rows-3"] $ do displayCategories categories displayLicense (metadata ^. #license) displayLinks packageName latestRelease metadata - div_ [class_ "col-span-2"] mempty div_ [class_ "package-right-column"] $ do div_ [class_ "grid-rows-3"] $ do displayInstructions packageName latestRelease diff --git a/src/FloraWeb/Templates/Pages/Search.hs b/src/FloraWeb/Templates/Pages/Search.hs index 99de03a4..910a5ef4 100644 --- a/src/FloraWeb/Templates/Pages/Search.hs +++ b/src/FloraWeb/Templates/Pages/Search.hs @@ -6,17 +6,14 @@ import qualified Data.Vector as V import Distribution.Types.Version (Version) import Flora.Model.Package (Namespace, PackageName) import FloraWeb.Templates -import FloraWeb.Templates.Packages.Listing (packageListing, presentationHeader) +import FloraWeb.Templates.Packages.Listing (packageListing, searchResultsAside) import Lucid -showResults :: Text -> Vector (Namespace, PackageName, Text, Version) -> FloraHTML -showResults searchString packagesInfo = do - div_ [class_ "container dark:text-gray-100 text-black"] $ do - presentationHeader searchString (fromIntegral $ V.length packagesInfo) - packageListing packagesInfo - showAllPackages :: Vector (Namespace, PackageName, Text, Version) -> FloraHTML -showAllPackages packagesInfo = do - div_ [class_ "container dark:text-gray-100 text-black"] $ do - presentationHeader "" (fromIntegral $ V.length packagesInfo) - packageListing packagesInfo +showAllPackages = showResults Nothing + +showResults :: Maybe Text -> Vector (Namespace, PackageName, Text, Version) -> FloraHTML +showResults searchString packagesInfo = do + div_ [class_ "container px-2 grid md:grid-cols-4 md:gap-6"] $ do + div_ [class_ "md:mt-6"] $ searchResultsAside searchString (fromIntegral $ V.length packagesInfo) + div_ [class_ "md:col-span-3"] $ packageListing packagesInfo diff --git a/src/FloraWeb/Templates/Pages/Sessions.hs b/src/FloraWeb/Templates/Pages/Sessions.hs index 29996797..cd8c3398 100644 --- a/src/FloraWeb/Templates/Pages/Sessions.hs +++ b/src/FloraWeb/Templates/Pages/Sessions.hs @@ -4,40 +4,35 @@ import FloraWeb.Templates.Types import Lucid newSession :: FloraHTML -newSession = - div_ [class_ "login-form max-w-md mx-auto flex justify-center"] $ do - div_ [class_ "ml-5"] $ - h2_ [class_ "mt-6 text-center text-3xl font-extrabold text-gray-900 dark:text-gray-100"] $ do - "Sign in" - form_ [class_ "mt-8 space-y-6", action_ "/sessions/new", method_ "POST"] $ do - div_ [class_ "rounded-md shadow-sm -space-y-px"] $ do - let fieldClass = "appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:z-10 sm:text-sm" - div_ $ do - label_ [for_ "email", class_ "sr-only"] "Email address" - input_ - [ id_ "email" - , name_ "email" - , type_ "email" - , autocomplete_ "email" - , required_ "" - , placeholder_ "Email address" - , class_ fieldClass - ] - div_ $ do - label_ [for_ "password", class_ "sr-only"] "Email address" - input_ - [ id_ "password" - , name_ "password" - , type_ "password" - , autocomplete_ "current-password" - , required_ "" - , placeholder_ "Password" - , class_ fieldClass - ] - div_ $ do - label_ [for_ "remember", class_ "text-xl mr-3"] "Remember me" - input_ [id_ "remember", name_ "remember", type_ "checkbox", class_ ""] +newSession = do + let formClasses = "login-form max-w-md mx-auto justify-center px-2 mt-12" + form_ [action_ "/sessions/new", method_ "POST", class_ formClasses] $ do + h2_ [class_ "text-center text-3xl mb-3 font-extrabold text-gray-900 dark:text-gray-100"] "Sign in" + div_ $ do + label_ [for_ "email", class_ "sr-only"] "Email address" + input_ + [ id_ "email" + , name_ "email" + , type_ "email" + , autocomplete_ "email" + , required_ "" + , placeholder_ "Email address" + , class_ "form-input block w-full" + ] + div_ $ do + label_ [for_ "password", class_ "sr-only"] "Email address" + input_ + [ id_ "password" + , name_ "password" + , type_ "password" + , autocomplete_ "current-password" + , required_ "" + , placeholder_ "Password" + , class_ "form-input block w-full" + ] + div_ $ do + label_ [for_ "remember", class_ "text-xl mr-3"] "Remember me" + input_ [id_ "remember", name_ "remember", type_ "checkbox", class_ ""] - div_ $ - button_ [type_ "submit", class_ "group relative w-full flex justify-center border border-transparent text-sm font-medium rounded-md text-white"] $ - span_ [class_ "absolute left-0 inset-y-0 flex items-center pl-3"] "Sign in" + div_ $ + button_ [type_ "submit", class_ "btn bg-brand-purple text-white w-full my-2"] "Sign in" diff --git a/src/FloraWeb/Templates/Types.hs b/src/FloraWeb/Templates/Types.hs index eef735d5..451742c2 100644 --- a/src/FloraWeb/Templates/Types.hs +++ b/src/FloraWeb/Templates/Types.hs @@ -43,6 +43,7 @@ data TemplateEnv = TemplateEnv , flashInfo :: Maybe FlashInfo , flashError :: Maybe FlashError , title :: Text + , mobileTitle :: Text , description :: Text , mUser :: Maybe User , sessionId :: PersistentSessionId @@ -64,6 +65,7 @@ data TemplateDefaults = TemplateDefaults , flashInfo :: Maybe FlashInfo , flashError :: Maybe FlashError , title :: Text + , mobileTitle :: Text , description :: Text , mUser :: Maybe User , environment :: DeploymentEnv @@ -86,6 +88,7 @@ defaultTemplateEnv = , flashInfo = Nothing , flashError = Nothing , title = "Flora :: [Package]" + , mobileTitle = "☰ Flora" , description = "Package index for the Haskell ecosystem" , mUser = Nothing , environment = Development