diff --git a/.circleci/config.yml b/.circleci/config.yml index 2cf3d68..8680f3a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,15 +7,29 @@ jobs: steps: - checkout - run: npx prettier . --check + # Install dependencies + - run: npm ci + # TODO : do we need caching for dependencies? + # Build the application + - run: npm run build # TODO: check that style.css matches compiled tailwind + # Store the build artifacts to be used in the deploy job + - persist_to_workspace: + root: . + paths: + - dist + - scripts deploy: docker: - # specify the version you desire here - image: cimg/node:20.8.1 working_directory: ~/repo steps: - checkout + # Attach the workspace with the build artifacts + - attach_workspace: + at: . + # Deploy using the script - run: ./scripts/deploy.sh workflows: diff --git a/.gitignore b/.gitignore index d9e5e60..c962116 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ pnpm-debug.log* lerna-debug.log* node_modules +dist +dist-ssr *.local # Editor directories and files diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 009ba8f..0000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -public/style.css \ No newline at end of file diff --git a/README.md b/README.md index 4868384..eaa1b00 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ [![Ceasefire Now](https://badge.techforpalestine.org/ceasefire-now)](https://techforpalestine.org/learn-more) +## Get started + +- `npm i` to install dependencies +- `npm run dev` to build and watch the CSS + ## Formatting To format, use VSCode Prettier extension, or run: @@ -13,7 +18,7 @@ To check it: `npx prettier --check .` Formatting in checked in CI -## Start the Tailwind CLI build process -To build and watch the CSS, use the following command: -`npm run dev` +## TODOs +- [ ] is there a better way than `~/assets/...` to reference things? + `~/assets/..` \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..79a552e --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,28 @@ +import js from "@eslint/js"; +import globals from "globals"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + { ignores: ["dist"] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ["**/*.{ts,tsx}"], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + "react-hooks": reactHooks, + "react-refresh": reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + "react-refresh/only-export-components": [ + "warn", + { allowConstantExport: true }, + ], + }, + }, +); diff --git a/index.html b/index.html new file mode 100644 index 0000000..f1507ac --- /dev/null +++ b/index.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + Darklang + + + +
+ + + diff --git a/package-lock.json b/package-lock.json index 9bd7e86..1d90c12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,363 +1,3086 @@ { "name": "darklang.com", + "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "darklang.com", + "version": "0.0.0", "dependencies": { - "@tailwindcss/line-clamp": "^0.4.4" + "@tailwindcss/vite": "^4.1.4", + "highlight.js": "^11.11.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-router-dom": "^7.5.0", + "tailwindcss": "^4.1.4" }, "devDependencies": { - "prettier": "3.0.3", - "tailwindcss": "^3.2.7" + "@eslint/js": "^9.21.0", + "@types/node": "^22.15.3", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.21.0", + "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^15.15.0", + "prettier": "3.5.3", + "typescript": "~5.7.2", + "typescript-eslint": "^8.24.1", + "vite": "^6.2.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.0.tgz", + "integrity": "sha512-WhCn7Z7TauhBtmzhvKpoQs0Wwb/kBcy4CwpuI0/eEIr2Lx2auxmulAzLr91wVZJaz47iUZdkXOK7WlAfxGKCnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", + "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", + "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", + "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", + "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", + "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", + "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", + "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", + "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", + "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", + "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", + "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", + "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", + "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", + "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", + "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", + "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", + "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", + "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", + "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", + "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", + "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", + "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.4.tgz", + "integrity": "sha512-MT5118zaiO6x6hNA04OWInuAiP1YISXql8Z+/Y8iisV5nuhM8VXlyhRuqc2PEviPszcXI66W44bCIk500Oolhw==", + "license": "MIT", + "dependencies": { + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.29.2", + "tailwindcss": "4.1.4" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.4.tgz", + "integrity": "sha512-p5wOpXyOJx7mKh5MXh5oKk+kqcz8T+bA3z/5VWWeQwFrmuBItGwz8Y2CHk/sJ+dNb9B0nYFfn0rj/cKHZyjahQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.4", + "@tailwindcss/oxide-darwin-arm64": "4.1.4", + "@tailwindcss/oxide-darwin-x64": "4.1.4", + "@tailwindcss/oxide-freebsd-x64": "4.1.4", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.4", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.4", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.4", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.4", + "@tailwindcss/oxide-linux-x64-musl": "4.1.4", + "@tailwindcss/oxide-wasm32-wasi": "4.1.4", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.4", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.4" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.4.tgz", + "integrity": "sha512-xMMAe/SaCN/vHfQYui3fqaBDEXMu22BVwQ33veLc8ep+DNy7CWN52L+TTG9y1K397w9nkzv+Mw+mZWISiqhmlA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.4.tgz", + "integrity": "sha512-JGRj0SYFuDuAGilWFBlshcexev2hOKfNkoX+0QTksKYq2zgF9VY/vVMq9m8IObYnLna0Xlg+ytCi2FN2rOL0Sg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.4.tgz", + "integrity": "sha512-sdDeLNvs3cYeWsEJ4H1DvjOzaGios4QbBTNLVLVs0XQ0V95bffT3+scptzYGPMjm7xv4+qMhCDrkHwhnUySEzA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.4.tgz", + "integrity": "sha512-VHxAqxqdghM83HslPhRsNhHo91McsxRJaEnShJOMu8mHmEj9Ig7ToHJtDukkuLWLzLboh2XSjq/0zO6wgvykNA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.4.tgz", + "integrity": "sha512-OTU/m/eV4gQKxy9r5acuesqaymyeSCnsx1cFto/I1WhPmi5HDxX1nkzb8KYBiwkHIGg7CTfo/AcGzoXAJBxLfg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.4.tgz", + "integrity": "sha512-hKlLNvbmUC6z5g/J4H+Zx7f7w15whSVImokLPmP6ff1QqTVE+TxUM9PGuNsjHvkvlHUtGTdDnOvGNSEUiXI1Ww==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.4.tgz", + "integrity": "sha512-X3As2xhtgPTY/m5edUtddmZ8rCruvBvtxYLMw9OsZdH01L2gS2icsHRwxdU0dMItNfVmrBezueXZCHxVeeb7Aw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.4.tgz", + "integrity": "sha512-2VG4DqhGaDSmYIu6C4ua2vSLXnJsb/C9liej7TuSO04NK+JJJgJucDUgmX6sn7Gw3Cs5ZJ9ZLrnI0QRDOjLfNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.4.tgz", + "integrity": "sha512-v+mxVgH2kmur/X5Mdrz9m7TsoVjbdYQT0b4Z+dr+I4RvreCNXyCFELZL/DO0M1RsidZTrm6O1eMnV6zlgEzTMQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.4.tgz", + "integrity": "sha512-2TLe9ir+9esCf6Wm+lLWTMbgklIjiF0pbmDnwmhR9MksVOq+e8aP3TSsXySnBDDvTTVd/vKu1aNttEGj3P6l8Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@emnapi/wasi-threads": "^1.0.1", + "@napi-rs/wasm-runtime": "^0.2.8", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.4.tgz", + "integrity": "sha512-VlnhfilPlO0ltxW9/BgfLI5547PYzqBMPIzRrk4W7uupgCt8z6Trw/tAj6QUtF2om+1MH281Pg+HHUJoLesmng==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.4.tgz", + "integrity": "sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.4.tgz", + "integrity": "sha512-4UQeMrONbvrsXKXXp/uxmdEN5JIJ9RkH7YVzs6AMxC/KC1+Np7WZBaNIco7TEjlkthqxZbt8pU/ipD+hKjm80A==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.4", + "@tailwindcss/oxide": "4.1.4", + "tailwindcss": "4.1.4" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz", + "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz", + "integrity": "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", + "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/type-utils": "8.30.1", + "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", + "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/typescript-estree": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", + "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", + "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.30.1", + "@typescript-eslint/utils": "8.30.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", + "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", + "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", + "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/typescript-estree": "8.30.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", + "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.30.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.0.tgz", + "integrity": "sha512-x/EztcTKVj+TDeANY1WjNeYsvZjZdfWRMP/KXi5Yn8BoTzpa13ZltaQqKfvWYbX8CE10GOHHdC5v86jY9x8i/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001713", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz", + "integrity": "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "ms": "^2.1.3" }, "engines": { - "node": ">= 8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/electron-to-chromium": { + "version": "1.5.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.137.tgz", + "integrity": "sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">= 8" + "node": ">=10.13.0" } }, - "node_modules/@tailwindcss/line-clamp": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz", - "integrity": "sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==", - "peerDependencies": { - "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + "node_modules/esbuild": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.2", + "@esbuild/android-arm": "0.25.2", + "@esbuild/android-arm64": "0.25.2", + "@esbuild/android-x64": "0.25.2", + "@esbuild/darwin-arm64": "0.25.2", + "@esbuild/darwin-x64": "0.25.2", + "@esbuild/freebsd-arm64": "0.25.2", + "@esbuild/freebsd-x64": "0.25.2", + "@esbuild/linux-arm": "0.25.2", + "@esbuild/linux-arm64": "0.25.2", + "@esbuild/linux-ia32": "0.25.2", + "@esbuild/linux-loong64": "0.25.2", + "@esbuild/linux-mips64el": "0.25.2", + "@esbuild/linux-ppc64": "0.25.2", + "@esbuild/linux-riscv64": "0.25.2", + "@esbuild/linux-s390x": "0.25.2", + "@esbuild/linux-x64": "0.25.2", + "@esbuild/netbsd-arm64": "0.25.2", + "@esbuild/netbsd-x64": "0.25.2", + "@esbuild/openbsd-arm64": "0.25.2", + "@esbuild/openbsd-x64": "0.25.2", + "@esbuild/sunos-x64": "0.25.2", + "@esbuild/win32-arm64": "0.25.2", + "@esbuild/win32-ia32": "0.25.2", + "@esbuild/win32-x64": "0.25.2" } }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", + "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.24.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, "bin": { - "acorn": "bin/acorn" + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=0.4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.19.tgz", + "integrity": "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" } }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "node_modules/eslint-scope": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=0.4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/anymatch": { + "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": ">= 8" + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", "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" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.12.0" } }, - "node_modules/defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" + "argparse": "^2.0.1" }, "bin": { - "detective": "bin/detective.js" + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=0.8.0" + "node": ">=6" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "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" + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": ">=8.6.0" + "node": ">=6" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "json-buffer": "3.0.1" } }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/lightningcss": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", + "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "license": "MPL-2.0", "dependencies": { - "to-regex-range": "^5.0.1" + "detect-libc": "^2.0.3" }, "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.29.2", + "lightningcss-darwin-x64": "1.29.2", + "lightningcss-freebsd-x64": "1.29.2", + "lightningcss-linux-arm-gnueabihf": "1.29.2", + "lightningcss-linux-arm64-gnu": "1.29.2", + "lightningcss-linux-arm64-musl": "1.29.2", + "lightningcss-linux-x64-gnu": "1.29.2", + "lightningcss-linux-x64-musl": "1.29.2", + "lightningcss-win32-arm64-msvc": "1.29.2", + "lightningcss-win32-x64-msvc": "1.29.2" } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", + "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", + "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10.13.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", + "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", + "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", + "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dependencies": { - "has": "^1.0.3" + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", + "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", + "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", + "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", + "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", + "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -366,6 +3089,8 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -374,24 +3099,37 @@ "node": ">=8.6" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -399,55 +3137,126 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -462,117 +3271,32 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -583,10 +3307,21 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -600,67 +3335,145 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", "dependencies": { - "pify": "^2.3.0" + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.0.tgz", + "integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==", + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "node_modules/react-router-dom": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.5.0.tgz", + "integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==", + "license": "MIT", "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "react-router": "7.5.0" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=20.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, + "node_modules/rollup": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz", + "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.40.0", + "@rollup/rollup-android-arm64": "4.40.0", + "@rollup/rollup-darwin-arm64": "4.40.0", + "@rollup/rollup-darwin-x64": "4.40.0", + "@rollup/rollup-freebsd-arm64": "4.40.0", + "@rollup/rollup-freebsd-x64": "4.40.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", + "@rollup/rollup-linux-arm-musleabihf": "4.40.0", + "@rollup/rollup-linux-arm64-gnu": "4.40.0", + "@rollup/rollup-linux-arm64-musl": "4.40.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-musl": "4.40.0", + "@rollup/rollup-linux-s390x-gnu": "4.40.0", + "@rollup/rollup-linux-x64-gnu": "4.40.0", + "@rollup/rollup-linux-x64-musl": "4.40.0", + "@rollup/rollup-win32-arm64-msvc": "4.40.0", + "@rollup/rollup-win32-ia32-msvc": "4.40.0", + "@rollup/rollup-win32-x64-msvc": "4.40.0", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -675,73 +3488,112 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tailwindcss": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", - "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", - "dependencies": { - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.0.9", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": ">=8" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz", + "integrity": "sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -749,25 +3601,238 @@ "node": ">=8.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">=0.4" + "node": ">= 0.8.0" } }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">= 6" + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", + "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.30.1", + "@typescript-eslint/parser": "8.30.1", + "@typescript-eslint/utils": "8.30.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "6.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", + "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "postcss": "^8.5.3", + "rollup": "^4.30.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } } diff --git a/package.json b/package.json index 3ab997f..7c98ad4 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,35 @@ { - "devDependencies": { - "prettier": "3.0.3", - "tailwindcss": "^3.2.7" - }, + "name": "darklang.com", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "dev": "npx tailwindcss -i ./src/input.css -o ./public/style.css --watch" + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" }, "dependencies": { - "@tailwindcss/line-clamp": "^0.4.4" + "@tailwindcss/vite": "^4.1.4", + "highlight.js": "^11.11.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-router-dom": "^7.5.0", + "tailwindcss": "^4.1.4" + }, + "devDependencies": { + "@eslint/js": "^9.21.0", + "@types/node": "^22.15.3", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.21.0", + "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^15.15.0", + "prettier": "3.5.3", + "typescript": "~5.7.2", + "typescript-eslint": "^8.24.1", + "vite": "^6.2.0" } } diff --git a/public/classic.html b/public/classic.html deleted file mode 100644 index 1bb8f79..0000000 --- a/public/classic.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - Darklang Classic - - - - - - - -
-
- - - - - - - - -

- #FreePalestine. - Read our founder's - statement -

-
- - - -
- - -
- logo -
- - -
-

- Dark is a new - way of building serverless backends. Just code your backend, with no - infra, framework or deployment nightmares. Build - APIs, - CRUD apps, - internal tools and - bots - whatever your backend - needs. -

- -

- The classic version of darklang is still accessible but is currently - in maintenance mode, with no ongoing development. Darklang-next is the - next iteration of Dark, applicable to both the cloud runtime and to - local scripts and CLIs -

-
- - -
- - - - - - Internal Tools & Bots - - - Dark is ideal for quickly building slackbots and automating internal - tools. Receive webhooks live, call out to 3rd party APIs, store - data, and schedule jobs - while building no infrastructure. - -

- Read more about using dark with Slack -

-
-
- - - - REST APIs & Webhooks - - - Set up an API endpoint quickly enough to use it as a proof of - concept during a call. Immediately see the data from a webhook to - your endpoint. Call an external API using the HttpClient library and - see responses within the editor, or use workers to do them in the - background. Use the built-in package manager to make external API - calls really easily, and contribute your own API integrations. - - - - - - CRUD apps - - - Get a working CRUD application in less than ten minutes by setting - up a few API endpoints and a datastore. Build out the backend for a - web or mobile app, whether a simple HTML form or an entire product. - - -
-
- - -
- AnyBackend That - Requires... -
- - - - API Endpoints - - - - - Data Stores - - - - - Background Workers - - - - - Scheduled Jobs - - - - -
-

- Dark lets you build any backend that needs API endpoints, data stores, - background workers, scheduled jobs, and calling HTTP APIs. You just - write the code in Dark, and we'll manage the rest. -

-
- -
- -

see it in action!

-
-
-
- - -
-

Access Darklang-classic

- -
- Sign up - or - Log in -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/classic/signup.html b/public/classic/signup.html deleted file mode 100644 index 5364061..0000000 --- a/public/classic/signup.html +++ /dev/null @@ -1,477 +0,0 @@ - - - - - - Signup - - - - - - - - - - - -
-
- logo -

- We're currently focused on the - next version - of Darklang, but you can still try Darklang Classic! -

-
- -
-
- - -

Sign up

- - - -
- - -
- -
- - -
- -
- - -
- -
- - -
- -

- Already have an account? - log in -

-
-
-
- - - - - - - - diff --git a/public/classic/signup.js b/public/classic/signup.js deleted file mode 100644 index f2e92aa..0000000 --- a/public/classic/signup.js +++ /dev/null @@ -1,73 +0,0 @@ -function clearErrors() { - document.querySelector("#error-list").innerHTML = ""; - document.querySelector("#errors").style.display = "none"; -} - -function showErrors(errors) { - clearErrors(); - - document.querySelector("#errors").style.display = "flex"; - - const errorList = document.querySelector("#error-list"); - - for (var i = 0; i < errors.length; i++) { - let newLI = document.createElement("li"); - newLI.appendChild(document.createTextNode(errors[i])); - - errorList.appendChild(newLI); - } -} - -function showSuccess() { - const form = document.getElementById("sign-up-form"); - const successMsg = document.getElementById("success"); - form.innerHTML = ""; - successMsg.classList.remove("hidden"); - successMsg.classList.add("flex"); - form.append(successMsg); -} - -async function submitForm(event) { - event.preventDefault(); - - const codeOfConductInput = document.querySelector("#code-of-conduct"); - - if (!codeOfConductInput.checked) { - showErrors(["Please agree to our code of conduct"]); - return; - } - - const nameInput = document.querySelector("#name"); - const emailInput = document.querySelector("#email"); - const usernameInput = document.querySelector("#username"); - - const form = document.querySelector("form"); - - const data = { - name: nameInput.value, - email: emailInput.value.toLowerCase(), - username: usernameInput.value, - }; - - const response = await fetch( - "https://ops-adduser.builtwithdark.com/v3/create-account", - { - method: "POST", - dataType: "json", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify(data), - }, - ); - if (response.status === 200) { - form.reset(); - showSuccess(); - } else { - const errorText = await response.text(); - showErrors([errorText]); - } -} - -document.querySelector("#sign-up-form").addEventListener("submit", submitForm); diff --git a/public/img/logo-dark-transparent.png b/public/img/logo-dark-transparent.png deleted file mode 100644 index 6e4ddd4..0000000 Binary files a/public/img/logo-dark-transparent.png and /dev/null differ diff --git a/public/img/wordmark-light-transparent@2x.png b/public/img/wordmark-light-transparent@2x.png deleted file mode 100644 index 0a5aea1..0000000 Binary files a/public/img/wordmark-light-transparent@2x.png and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 52bb1c7..0000000 --- a/public/index.html +++ /dev/null @@ -1,1479 +0,0 @@ - - - - - - Darklang - - - - - - - - - - - - - - - - -
-
- - - - - - - - -

- #FreePalestine. - Read our founder's - statement -

-
- - - -
- - -
-
- logo -
- -
-
-

- Just - code -

-

- no cruft: no build systems, no - null, no exception handling, no ORMs, no OOP, no inheritence - hierarchies, no async/await, no compilation, no dev environments, - no dependency hell, no packaging, no git, no github, - - no devops: no yaml, no config - files, no docker, no containers, no kubernetes, no ci/cd - pipelines, no terraform, no orchestrating, - - no infrastructure: no sql, no - nosql, no connection poolers, no sharding, no indexes, no servers, - no serverless, no networking, no load balancers, no 200 cloud - services, no kafka, no memcached, no unix, no OSes -

-
- -
-
-

Send me project updates

-
- - - -
-
-
-
-
- - -
-

- Darklang puts everything in one box, so you can build CLIs and cloud - apps with no bullshit, - just - code. -

-
-

- ️️️Also it's a really enjoyable language to use! -

-
- - -
-
-
-

- Looking for Darklang-classic? -

- -
-
- dark-classic -
-
-
- -
-
-
- In development - here’s how things will look shortly -
-
- -
- -
-
-              $ curl https://darklang.com/download | bash 
-              
-              Darklang installed in ~/.darklang/bin/darklang
-              
-              Add to PATH via .bashrc [y, n, ?]: y 
-              Added to .bashrc. 
-
-              Next you can: # Try the tutorial darklang tutorial # Run some code from the package manager darklang @paul.fizzbuzz 3 # Generate some code darklang prompt "Find ts scripts with more than 600 lines which use the commonjs format"# See available command line optionsdarklang help
-              
-            
-
-
- - -
- -
-                
-                $ darklang @paul.fizzbuzz 3 
-                1
-                2 
-                Fizz
-                
-              
-
- - -
-                
-                $ darklang deploy @paul.fizzbuzz /fizzbuzz 
-                Deployed to https://furry-squirrel-3562.darklang.io/fizzbuzz in 0.135s
-                 
-              
-
- - -
-                
-                $ curl -sSO https://furry-squirrel-3562.darklang.io/fizzbuzz/3 
-                1 
-                2 
-                Fizz
-                
-              
-
-
-
- -
- - -
-
-                $ darklang prompt "Find ts scripts with more than 600 lines which use commonjs format" 
-
-                We need your AI credentials, which will be stored locally in ~/darklang/secrets/
-
-                [1] Login to use Darklang AI service 
-                [2] Enter GitHub copilot credentials 
-                [3] Enter OpenAI (GPT 3.5/4) credentials 
-                [4] Use local model 
-
-                Enter [1-4]: 1 
-
-                Login or register [L, r]? L
-                Username: paul
-                Password: **************
-
-                Logged in.
-
-                Saved script in ./find-large-ts-cjs.dark in 43.8s
-
-                
-
- - -
-
-
- dark-file-logo -
-
-

find-large-ts-cjs.dark

-
-
- -
-
let findLargeTypescriptCommonJSFiles (path : String) =
-  Directory.traverse (fun path -> 
-    if not (List.oneOf (File.extension path) [".ts", ".mjs", ".cjs"]) then 
-      print $"Skipping - wrong file type: {path}" 
-    else 
-      let contents = File.readString path 
-      let lines = String.splitNewlines contents
-      if (List.length lines) <= 600 then 
-        print $"Skipping - too short: {path}" 
-      else 
-        let isCommonjs = 
-          lines |> List.any (fun line ->
-            line |> Regex.matches "/const .* = require(.*)/" 
-          ) 
-        if isCommonjs then 
-          print $"Found one: {path}" 
-    )
-    
-findLargeTypescriptCommonJSFiles "./"
-
-
-
-
-
- - -
- - - Functional language - - - Simple types using Records and - Enums - - Dynamic languages are great, allowing great flexibility. But now - that they've matured and projects have gotten larger, static - typing has been layered on top of very dynamic languages, and the - intersection is not pleasant. Functional static languages like - Darklang have simple Record and Enum types that can model nearly - everything with much less complexity. - - - - - Abstract Data Types made of Record - and Enums can model nearly anything, like in Rust, Elm, OCaml - and F# -
-// Record
-type Url = {
-  scheme : HttpScheme
-  domain : String
-  port : UInt16
-  path : String
-  query : Option<String>
-}
-
-// Enum (aka Variant, Sum Type, or Abstract Data Types)
-type UrlError = 
-  | InvalidScheme(String)
-  | EmptyDomain
-  | InvalidPort(Int64)
-  | Unparseable(msg:String, context:String)
-
-// Aliases are just shorthands
-type UrlParseResult = Result<Url, UrlError>
-
-
-
- - - We believe Object Oriented programming is a terrible way to - model programs, and inheritence is a terrible misfeature. - Languages like OCaml, Elm, and F# have shown that nearly all - problems can be modeled using ADTs. - -
-
-
- - - Option and - Result types instead of null and - exceptions - - I think it's widely accepted that - nullis a mistake, and that an - Optiontype (aka - Optional, - Maybe, etc) makes it significantly - easier to program. - - - - - We further believe that Exceptions — which can in most - languages be thrown at any point — makes it very frustrating - to know that a function actually works. There are no - exceptions in Darklang, and we use - Result types to manage error cases - - - ? and - !operators (similar to Rust, - TypeScript, and Clojure) provide ways to ergonomically handle - errors without being too annoying (see also Gradual Static - Typing) - - - We will admit we have some RuntimeErrors which cannot be - caught, but we are working to remove them almost entirely from - the language (see Gradual Static Typing for what we're - keeping) - - - - - - - Garbage Collected - - It can be fun to satisfy the borrow checker, or manage allocations - individually, but it can also be fun to just get working programs - immediately. We believe that run-time garbage collection is one of - the greatest programming language features, and we're all in - - - - - - Unicode First - - Languages created last millennium typically use Strings made of - bytes, or worse, UTF16 characters, or even worse, Unicode - Codepoints! Like Swift, we believe that - Characters should represent screen - readable characters, like 👨‍👩‍👦‍👦. All characters in Darklang represent - Extended Grapheme Clusters: one - character that you see on screen. Naturally, working on Unicode - Codepoints and normal bytes is also well - supported. - - - -
-
- - - - Runs Instantly - - - - Instantly run any package from - the CLI: - - darklang - @username.functionName - arg1 - arg2 - - - - - Darklang has a new model of sharing programs. Any function in the - package manager can be called directly from the command line (so - long as we can figure out how to coerce the command line arguments - correctly) - - - -
$ darklang @paul.fizzbuzz 10
-1
-2
-Fizz
-4
-Buzz
-Fizz
-7
-8
-Fizz
-Buzz 
- - - We designed this to allow you to share scripts with your team, - or the whole world. We support private packages - , with individual, team, or role-based access - controls. You can even have functions that run - server-side - without allowing the user to see credentials, for example for - providing customer support tools to your team. - - - Functions can also be run from the web, Slack, Discord, etc - - - - We're building safety features, to ensure that functions - can't just steal all your IDs and wallets and whatever. - Darklang asks for permissions when you call a function, and a - static analysis is run to collect all permissions needed. -
$ darklang @hacker.stealThings "Hi there"
-> @hacker.stealThings requires the following permissions
->   Makes Http requests to unknown domains
->   Reads any file
->   Executes any file
-> Continue? [N, y] y
-> These are unusual permissions. Are you sure [N, y] y
-Ha ha, you're own3d
-
-$ darklang @mycompany.internal.createMonthlyReport
-> @mycompany.internal.createMonthlyReport requires the following
-> permissions
->   Makes Http GET requests to stripe.com/api/ETC
->   Makes Http POST requests to drive.google.com
-> Continue? [N, y] y
-Report initiated and stored at https://drive.google.com/u/asj599b3/5288942sdfsdf3.pdf
-
-
-
-
- - - - Instantly run programs as you - write them - - - Darklang is designed for a really fast iterative loop - - - - - Single binary to install means no environments or containers - to set up. - Install it now! - Coming early 2025 - - - Packages are streamed from the package manager automatically - – no - npm install step - - - darklang is interpreted — no compilation step required, - programs run immediately - -
    - - We plan to add background compilation in the future, - combined with pre-compiled packages in the package manager - - -
- - - Gradual Static Typing allows running programs with incorrect - types so you don't need to fix all the types in your program - while getting one path working - - - Generate darklang code automatically using LLMs and GitHub - Copilot - -
-
-
-
-
- - - - Next-gen package - management - - Darklang has a rather unique package manager, where functions and - types are individually versioned and immutable, taking a lot of the - hassle out of package management. - - - - Only download the specific package items you use - - - Only upgrade the specific package items you use - - - Automated dependency upgrades, as we track - deprecation status, and know what functions are pure and safe to - update. - - - Different packages can rely on different versions of other - packages - - - Use multiple versions of the same package item at once: allows - testing new versions without having to change an entire package - version, lowering risk. - - - Share pre-release functions trivially, without - contributors needing to check out your git repo or set up - anything - - - The package manager functions as a source - repository - - - no need for uploads, releases or other synchronization. No git - or GitHub required (but you can sync to GitHub if you prefer). - - - - - - - - - - Gradual Static Typing - - Gradual Static Typing allows running incomplete programs so you don't - need to ensure everything type checks when you're getting one path - working - - - - While prototyping, just run code until you hit a type error - - - After prototyping, run the full type checker to gain confidence - your whole program works - - - - Full type-checking hints in VSCode or in LSP editors - - - - ! and - ? operators allow easy error handling - while you prototype - - - Automatic refactoring converts - ! into proper error handling - - - - - - - - - - - Async runtime - - - - Fully asynchronous runtime - - - Darklang has a fully asynchronous runtime, so making a Http call - or reading a file doesn't block the runtime. - - - - - - No - async / - await - - - Adding - async and - await keywords to every language was a - mistake. It exposes the complexity of concurrency and - multi-threading to languages which were originally designed for - simplicity. - - - - - - Concurrent and - parallel execution via - data-dependencies - - -

- When you make an async request, it first waits for any arguments - that are async, and starts when they're done. If another - function call needs to use the result, it will wait for it - before starting. -

-

- Since darklang values are immutable, there won't be any race - conditions from this. -

-
-
- - - - Powerful escape hatches - - - We provide powerful escape hatches if you need async ordering that - doesn't match the data dependencies of your program. - - -
-
- - - - Instant cloud - deployment - - Optional - - Instant cloud deployment of code (to our cloud or yours), with instant - creation of DBs, API endpoints, and worker queues, with no containers, - no cold starts, no orchestration, or other devops/cloud engineering - required - - - - - - Designed for GenAI - - Works with GitHub Copilot - - We redesigned the dark language and tooling to enable - GenAI-generated programs, including exposing language tools to GenAI - tools, allowing running partial and incomplete programs safely, and - ensuring access to significant context to GenAI tools - - - - - Build short CLI programs from prompts - - darklang - prompt "find all js files - which don't have a CSS file of the same name" - - - - Use any LLM: darklang's fine-tuned models , local - OSS models, commerical models via API, or using GitHub Copilot - - - - - Build vendor SDKs from prompts and OpenAPI docs - - - - - Build complex programs with darklang AI agents - - - - - - - Works with your - Editor - - VSCode Extension - LSP support for other editors - - Works with GitHub Copilot and other GenAI tools - - - We mention this because Darklang classic required using our - editor, and that's no longer the case. - - - - - - - - Open source - - We expect to fully open source Darklang, which is currently source - available, early 2025 - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/signup.html b/public/signup.html deleted file mode 100644 index 2b896a2..0000000 --- a/public/signup.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - Signup - - - diff --git a/public/style.css b/public/style.css deleted file mode 100644 index d47ba49..0000000 --- a/public/style.css +++ /dev/null @@ -1,2307 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=League+Gothic&display=swap"); - -@import url("https://fonts.googleapis.com/css2?family=Assistant:wght@700&display=swap"); - -@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap"); - -@import url("https://fonts.googleapis.com/css2?family=Assistant:wght@700&family=Fira+Code:wght@400;500;600&display=swap"); - -/* -! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com -*/ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ -} - -::before, -::after { - --tw-content: ''; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -*/ - -html { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - -o-tab-size: 4; - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font family by default. -2. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-size: 1em; - /* 2 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -[type='button'], -[type='reset'], -[type='submit'] { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden] { - display: none; -} - -*, ::before, ::after{ - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; -} - -::backdrop{ - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; -} - -.container{ - width: 100%; -} - -@media (min-width: 640px){ - .container{ - max-width: 640px; - } -} - -@media (min-width: 768px){ - .container{ - max-width: 768px; - } -} - -@media (min-width: 1024px){ - .container{ - max-width: 1024px; - } -} - -@media (min-width: 1280px){ - .container{ - max-width: 1280px; - } -} - -@media (min-width: 1536px){ - .container{ - max-width: 1536px; - } -} - -.static{ - position: static; -} - -.absolute{ - position: absolute; -} - -.relative{ - position: relative; -} - -.sticky{ - position: sticky; -} - -.-inset-full{ - top: -100%; - right: -100%; - bottom: -100%; - left: -100%; -} - -.-bottom-7{ - bottom: -1.75rem; -} - -.left-0{ - left: 0px; -} - -.right-4{ - right: 1rem; -} - -.top-0{ - top: 0px; -} - -.top-3{ - top: 0.75rem; -} - -.z-10{ - z-index: 10; -} - -.z-50{ - z-index: 50; -} - -.m-0{ - margin: 0px; -} - -.m-10{ - margin: 2.5rem; -} - -.m-2{ - margin: 0.5rem; -} - -.m-3{ - margin: 0.75rem; -} - -.m-4{ - margin: 1rem; -} - -.mx-12{ - margin-left: 3rem; - margin-right: 3rem; -} - -.mx-2{ - margin-left: 0.5rem; - margin-right: 0.5rem; -} - -.mx-3{ - margin-left: 0.75rem; - margin-right: 0.75rem; -} - -.mx-4{ - margin-left: 1rem; - margin-right: 1rem; -} - -.mx-auto{ - margin-left: auto; - margin-right: auto; -} - -.my-10{ - margin-top: 2.5rem; - margin-bottom: 2.5rem; -} - -.my-2{ - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - -.my-20{ - margin-top: 5rem; - margin-bottom: 5rem; -} - -.my-3{ - margin-top: 0.75rem; - margin-bottom: 0.75rem; -} - -.my-4{ - margin-top: 1rem; - margin-bottom: 1rem; -} - -.my-7{ - margin-top: 1.75rem; - margin-bottom: 1.75rem; -} - -.my-8{ - margin-top: 2rem; - margin-bottom: 2rem; -} - -.-ml-3{ - margin-left: -0.75rem; -} - -.mb-12{ - margin-bottom: 3rem; -} - -.mb-16{ - margin-bottom: 4rem; -} - -.mb-2{ - margin-bottom: 0.5rem; -} - -.mb-24{ - margin-bottom: 6rem; -} - -.mb-3{ - margin-bottom: 0.75rem; -} - -.mb-4{ - margin-bottom: 1rem; -} - -.mb-5{ - margin-bottom: 1.25rem; -} - -.mb-8{ - margin-bottom: 2rem; -} - -.ml-2{ - margin-left: 0.5rem; -} - -.ml-4{ - margin-left: 1rem; -} - -.ml-5{ - margin-left: 1.25rem; -} - -.mr-1{ - margin-right: 0.25rem; -} - -.mr-2{ - margin-right: 0.5rem; -} - -.mr-3{ - margin-right: 0.75rem; -} - -.mt-1{ - margin-top: 0.25rem; -} - -.mt-10{ - margin-top: 2.5rem; -} - -.mt-11{ - margin-top: 2.75rem; -} - -.mt-12{ - margin-top: 3rem; -} - -.mt-14{ - margin-top: 3.5rem; -} - -.mt-16{ - margin-top: 4rem; -} - -.mt-2{ - margin-top: 0.5rem; -} - -.mt-20{ - margin-top: 5rem; -} - -.mt-4{ - margin-top: 1rem; -} - -.mt-6{ - margin-top: 1.5rem; -} - -.mt-8{ - margin-top: 2rem; -} - -.box-border{ - box-sizing: border-box; -} - -.block{ - display: block; -} - -.inline-block{ - display: inline-block; -} - -.inline{ - display: inline; -} - -.flex{ - display: flex; -} - -.inline-flex{ - display: inline-flex; -} - -.grid{ - display: grid; -} - -.contents{ - display: contents; -} - -.hidden{ - display: none; -} - -.h-12{ - height: 3rem; -} - -.h-14{ - height: 3.5rem; -} - -.h-3{ - height: 0.75rem; -} - -.h-4{ - height: 1rem; -} - -.h-5{ - height: 1.25rem; -} - -.h-6{ - height: 1.5rem; -} - -.h-64{ - height: 16rem; -} - -.h-8{ - height: 2rem; -} - -.h-fit{ - height: -moz-fit-content; - height: fit-content; -} - -.h-full{ - height: 100%; -} - -.w-1\/2{ - width: 50%; -} - -.w-3{ - width: 0.75rem; -} - -.w-4{ - width: 1rem; -} - -.w-5{ - width: 1.25rem; -} - -.w-6{ - width: 1.5rem; -} - -.w-8{ - width: 2rem; -} - -.w-fit{ - width: -moz-fit-content; - width: fit-content; -} - -.w-full{ - width: 100%; -} - -.max-w-6xl{ - max-width: 72rem; -} - -.max-w-xs{ - max-width: 20rem; -} - -.flex-1{ - flex: 1 1 0%; -} - -.-translate-y-6{ - --tw-translate-y: -1.5rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.rotate-180{ - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.-skew-x-12{ - --tw-skew-x: -12deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.scale-75{ - --tw-scale-x: .75; - --tw-scale-y: .75; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.transform{ - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -@keyframes ping{ - 75%, 100%{ - transform: scale(2); - opacity: 0; - } -} - -.animate-ping{ - animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; -} - -.cursor-pointer{ - cursor: pointer; -} - -.appearance-none{ - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -.grid-cols-2{ - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -.flex-row{ - flex-direction: row; -} - -.flex-col{ - flex-direction: column; -} - -.flex-wrap{ - flex-wrap: wrap; -} - -.items-center{ - align-items: center; -} - -.justify-center{ - justify-content: center; -} - -.justify-between{ - justify-content: space-between; -} - -.gap-3{ - gap: 0.75rem; -} - -.gap-y-2{ - row-gap: 0.5rem; -} - -.overflow-hidden{ - overflow: hidden; -} - -.whitespace-pre-line{ - white-space: pre-line; -} - -.rounded{ - border-radius: 0.25rem; -} - -.rounded-2xl{ - border-radius: 1rem; -} - -.rounded-full{ - border-radius: 9999px; -} - -.rounded-lg{ - border-radius: 0.5rem; -} - -.rounded-md{ - border-radius: 0.375rem; -} - -.rounded-xl{ - border-radius: 0.75rem; -} - -.rounded-b-lg{ - border-bottom-right-radius: 0.5rem; - border-bottom-left-radius: 0.5rem; -} - -.rounded-t-lg{ - border-top-left-radius: 0.5rem; - border-top-right-radius: 0.5rem; -} - -.border{ - border-width: 1px; -} - -.border-0{ - border-width: 0px; -} - -.border-b{ - border-bottom-width: 1px; -} - -.border-blue{ - --tw-border-opacity: 1; - border-color: rgb(116 122 185 / var(--tw-border-opacity)); -} - -.border-classic-pink{ - --tw-border-opacity: 1; - border-color: rgb(245 111 240 / var(--tw-border-opacity)); -} - -.border-classic-purple{ - --tw-border-opacity: 1; - border-color: rgb(178 120 255 / var(--tw-border-opacity)); -} - -.border-gray-300{ - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} - -.border-gray-400{ - --tw-border-opacity: 1; - border-color: rgb(156 163 175 / var(--tw-border-opacity)); -} - -.border-white\/20{ - border-color: rgb(255 255 255 / 0.2); -} - -.border-b-blue\/25{ - border-bottom-color: rgb(116 122 185 / 0.25); -} - -.border-b-gray-600{ - --tw-border-opacity: 1; - border-bottom-color: rgb(75 85 99 / var(--tw-border-opacity)); -} - -.border-b-white\/10{ - border-bottom-color: rgb(255 255 255 / 0.1); -} - -.border-b-white\/20{ - border-bottom-color: rgb(255 255 255 / 0.2); -} - -.\!bg-code-background{ - --tw-bg-opacity: 1 !important; - background-color: rgb(245 244 241 / var(--tw-bg-opacity)) !important; -} - -.\!bg-dark-gray{ - --tw-bg-opacity: 1 !important; - background-color: rgb(47 47 47 / var(--tw-bg-opacity)) !important; -} - -.bg-\[\#19181D\]{ - --tw-bg-opacity: 1; - background-color: rgb(25 24 29 / var(--tw-bg-opacity)); -} - -.bg-\[\#1c1c1c\]{ - --tw-bg-opacity: 1; - background-color: rgb(28 28 28 / var(--tw-bg-opacity)); -} - -.bg-\[\#5FDD68\]{ - --tw-bg-opacity: 1; - background-color: rgb(95 221 104 / var(--tw-bg-opacity)); -} - -.bg-\[\#DD333F\]{ - --tw-bg-opacity: 1; - background-color: rgb(221 51 63 / var(--tw-bg-opacity)); -} - -.bg-\[\#E3D3FF\]{ - --tw-bg-opacity: 1; - background-color: rgb(227 211 255 / var(--tw-bg-opacity)); -} - -.bg-\[\#F5D76E\]{ - --tw-bg-opacity: 1; - background-color: rgb(245 215 110 / var(--tw-bg-opacity)); -} - -.bg-blue{ - --tw-bg-opacity: 1; - background-color: rgb(116 122 185 / var(--tw-bg-opacity)); -} - -.bg-classic-purple{ - --tw-bg-opacity: 1; - background-color: rgb(178 120 255 / var(--tw-bg-opacity)); -} - -.bg-cli-background{ - --tw-bg-opacity: 1; - background-color: rgb(38 38 38 / var(--tw-bg-opacity)); -} - -.bg-code-background{ - --tw-bg-opacity: 1; - background-color: rgb(245 244 241 / var(--tw-bg-opacity)); -} - -.bg-dark-gray{ - --tw-bg-opacity: 1; - background-color: rgb(47 47 47 / var(--tw-bg-opacity)); -} - -.bg-light-background{ - --tw-bg-opacity: 1; - background-color: rgb(250 250 250 / var(--tw-bg-opacity)); -} - -.bg-purple{ - --tw-bg-opacity: 1; - background-color: rgb(149 91 159 / var(--tw-bg-opacity)); -} - -.bg-red-300{ - --tw-bg-opacity: 1; - background-color: rgb(252 165 165 / var(--tw-bg-opacity)); -} - -.bg-transparent{ - background-color: transparent; -} - -.bg-white{ - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} - -.bg-white\/70{ - background-color: rgb(255 255 255 / 0.7); -} - -.bg-gradient-to-r{ - background-image: linear-gradient(to right, var(--tw-gradient-stops)); -} - -.from-classic-purple{ - --tw-gradient-from: #B278FF; - --tw-gradient-to: rgb(178 120 255 / 0); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.from-purple{ - --tw-gradient-from: #955B9F; - --tw-gradient-to: rgb(149 91 159 / 0); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.from-transparent{ - --tw-gradient-from: transparent; - --tw-gradient-to: rgb(0 0 0 / 0); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.via-classic-purple{ - --tw-gradient-to: rgb(178 120 255 / 0); - --tw-gradient-stops: var(--tw-gradient-from), #B278FF, var(--tw-gradient-to); -} - -.via-classic-purple\/80{ - --tw-gradient-to: rgb(178 120 255 / 0); - --tw-gradient-stops: var(--tw-gradient-from), rgb(178 120 255 / 0.8), var(--tw-gradient-to); -} - -.to-blue{ - --tw-gradient-to: #747AB9; -} - -.to-classic-pink{ - --tw-gradient-to: #F56FF0; -} - -.to-classic-pink\/80{ - --tw-gradient-to: rgb(245 111 240 / 0.8); -} - -.to-white{ - --tw-gradient-to: #fff; -} - -.bg-clip-text{ - -webkit-background-clip: text; - background-clip: text; -} - -.fill-current{ - fill: currentColor; -} - -.p-0{ - padding: 0px; -} - -.p-0\.5{ - padding: 0.125rem; -} - -.p-2{ - padding: 0.5rem; -} - -.p-4{ - padding: 1rem; -} - -.p-5{ - padding: 1.25rem; -} - -.p-6{ - padding: 1.5rem; -} - -.p-8{ - padding: 2rem; -} - -.px-1{ - padding-left: 0.25rem; - padding-right: 0.25rem; -} - -.px-1\.5{ - padding-left: 0.375rem; - padding-right: 0.375rem; -} - -.px-12{ - padding-left: 3rem; - padding-right: 3rem; -} - -.px-2{ - padding-left: 0.5rem; - padding-right: 0.5rem; -} - -.px-20{ - padding-left: 5rem; - padding-right: 5rem; -} - -.px-3{ - padding-left: 0.75rem; - padding-right: 0.75rem; -} - -.px-4{ - padding-left: 1rem; - padding-right: 1rem; -} - -.px-5{ - padding-left: 1.25rem; - padding-right: 1.25rem; -} - -.px-6{ - padding-left: 1.5rem; - padding-right: 1.5rem; -} - -.px-8{ - padding-left: 2rem; - padding-right: 2rem; -} - -.py-0{ - padding-top: 0px; - padding-bottom: 0px; -} - -.py-0\.5{ - padding-top: 0.125rem; - padding-bottom: 0.125rem; -} - -.py-1{ - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.py-2{ - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.py-3{ - padding-top: 0.75rem; - padding-bottom: 0.75rem; -} - -.py-4{ - padding-top: 1rem; - padding-bottom: 1rem; -} - -.py-8{ - padding-top: 2rem; - padding-bottom: 2rem; -} - -.pb-11{ - padding-bottom: 2.75rem; -} - -.pb-3{ - padding-bottom: 0.75rem; -} - -.pb-4{ - padding-bottom: 1rem; -} - -.pb-5{ - padding-bottom: 1.25rem; -} - -.pl-1{ - padding-left: 0.25rem; -} - -.pl-11{ - padding-left: 2.75rem; -} - -.pl-3{ - padding-left: 0.75rem; -} - -.pr-14{ - padding-right: 3.5rem; -} - -.pr-2{ - padding-right: 0.5rem; -} - -.pr-4{ - padding-right: 1rem; -} - -.pt-1{ - padding-top: 0.25rem; -} - -.pt-10{ - padding-top: 2.5rem; -} - -.text-left{ - text-align: left; -} - -.text-center{ - text-align: center; -} - -.text-justify{ - text-align: justify; -} - -.font-FiraCode{ - font-family: Fira Code, monospace; -} - -.font-Quicksand{ - font-family: Quicksand, sans-serif; -} - -.font-body{ - font-family: Inter, sans-serif; -} - -.text-2xl{ - font-size: 1.5rem; - line-height: 2rem; -} - -.text-3xl{ - font-size: 1.875rem; - line-height: 2.25rem; -} - -.text-4xl{ - font-size: 2.25rem; - line-height: 2.5rem; -} - -.text-7xl{ - font-size: 4.5rem; - line-height: 1; -} - -.text-base{ - font-size: 1rem; - line-height: 1.5rem; -} - -.text-lg{ - font-size: 1.125rem; - line-height: 1.75rem; -} - -.text-sm{ - font-size: 0.875rem; - line-height: 1.25rem; -} - -.text-xl{ - font-size: 1.25rem; - line-height: 1.75rem; -} - -.text-xs{ - font-size: 0.75rem; - line-height: 1rem; -} - -.font-bold{ - font-weight: 700; -} - -.font-medium{ - font-weight: 500; -} - -.font-normal{ - font-weight: 400; -} - -.font-semibold{ - font-weight: 600; -} - -.italic{ - font-style: italic; -} - -.leading-6{ - line-height: 1.5rem; -} - -.\!text-gray-600{ - --tw-text-opacity: 1 !important; - color: rgb(75 85 99 / var(--tw-text-opacity)) !important; -} - -.\!text-white{ - --tw-text-opacity: 1 !important; - color: rgb(255 255 255 / var(--tw-text-opacity)) !important; -} - -.text-\[\#02A5F1\]{ - --tw-text-opacity: 1; - color: rgb(2 165 241 / var(--tw-text-opacity)); -} - -.text-\[\#a1b56c\]{ - --tw-text-opacity: 1; - color: rgb(161 181 108 / var(--tw-text-opacity)); -} - -.text-black{ - --tw-text-opacity: 1; - color: rgb(0 0 0 / var(--tw-text-opacity)); -} - -.text-blue{ - --tw-text-opacity: 1; - color: rgb(116 122 185 / var(--tw-text-opacity)); -} - -.text-classic-blue{ - --tw-text-opacity: 1; - color: rgb(134 193 185 / var(--tw-text-opacity)); -} - -.text-classic-brown{ - --tw-text-opacity: 1; - color: rgb(161 136 127 / var(--tw-text-opacity)); -} - -.text-classic-green{ - --tw-text-opacity: 1; - color: rgb(161 181 108 / var(--tw-text-opacity)); -} - -.text-classic-purple{ - --tw-text-opacity: 1; - color: rgb(178 120 255 / var(--tw-text-opacity)); -} - -.text-classic-yellow{ - --tw-text-opacity: 1; - color: rgb(230 189 129 / var(--tw-text-opacity)); -} - -.text-dark-gray{ - --tw-text-opacity: 1; - color: rgb(47 47 47 / var(--tw-text-opacity)); -} - -.text-dark-gray\/50{ - color: rgb(47 47 47 / 0.5); -} - -.text-gray-300{ - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} - -.text-gray-400{ - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} - -.text-gray-500{ - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} - -.text-gray-600{ - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity)); -} - -.text-green-300{ - --tw-text-opacity: 1; - color: rgb(134 239 172 / var(--tw-text-opacity)); -} - -.text-lime-400{ - --tw-text-opacity: 1; - color: rgb(163 230 53 / var(--tw-text-opacity)); -} - -.text-purple{ - --tw-text-opacity: 1; - color: rgb(149 91 159 / var(--tw-text-opacity)); -} - -.text-red-400{ - --tw-text-opacity: 1; - color: rgb(248 113 113 / var(--tw-text-opacity)); -} - -.text-red-600{ - --tw-text-opacity: 1; - color: rgb(220 38 38 / var(--tw-text-opacity)); -} - -.text-red-800{ - --tw-text-opacity: 1; - color: rgb(153 27 27 / var(--tw-text-opacity)); -} - -.text-transparent{ - color: transparent; -} - -.text-white{ - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.underline{ - text-decoration-line: underline; -} - -.line-through{ - text-decoration-line: line-through; -} - -.underline-offset-2{ - text-underline-offset: 2px; -} - -.opacity-40{ - opacity: 0.4; -} - -.opacity-75{ - opacity: 0.75; -} - -.shadow-2xl{ - --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); - --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.blur-lg{ - --tw-blur: blur(16px); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.drop-shadow-md{ - --tw-drop-shadow: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06)); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.transition{ - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-all{ - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-transform{ - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.duration-200{ - transition-duration: 200ms; -} - -.duration-300{ - transition-duration: 300ms; -} - -.ease-in-out{ - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -} - -.line-clamp-3{ - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; -} - -.hljs-title.hljs-title{ - --tw-text-opacity: 1; - color: rgb(153 27 27 / var(--tw-text-opacity)); -} - -@media (min-width: 768px){ - .md\:container{ - width: 100%; - } - - @media (min-width: 640px){ - .md\:container{ - max-width: 640px; - } - } - - @media (min-width: 768px){ - .md\:container{ - max-width: 768px; - } - } - - @media (min-width: 1024px){ - .md\:container{ - max-width: 1024px; - } - } - - @media (min-width: 1280px){ - .md\:container{ - max-width: 1280px; - } - } - - @media (min-width: 1536px){ - .md\:container{ - max-width: 1536px; - } - } -} - -@media (min-width: 1536px){ - .\32xl\:container{ - width: 100%; - } - - @media (min-width: 640px){ - .\32xl\:container{ - max-width: 640px; - } - } - - @media (min-width: 768px){ - .\32xl\:container{ - max-width: 768px; - } - } - - @media (min-width: 1024px){ - .\32xl\:container{ - max-width: 1024px; - } - } - - @media (min-width: 1280px){ - .\32xl\:container{ - max-width: 1280px; - } - } - - @media (min-width: 1536px){ - .\32xl\:container{ - max-width: 1536px; - } - } -} - -.hover\:-translate-y-1:hover{ - --tw-translate-y: -0.25rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.hover\:bg-blue:hover{ - --tw-bg-opacity: 1; - background-color: rgb(116 122 185 / var(--tw-bg-opacity)); -} - -.hover\:bg-classic-purple:hover{ - --tw-bg-opacity: 1; - background-color: rgb(178 120 255 / var(--tw-bg-opacity)); -} - -.hover\:bg-classic-purple\/40:hover{ - background-color: rgb(178 120 255 / 0.4); -} - -.hover\:bg-pink-500:hover{ - --tw-bg-opacity: 1; - background-color: rgb(236 72 153 / var(--tw-bg-opacity)); -} - -.hover\:bg-purple:hover{ - --tw-bg-opacity: 1; - background-color: rgb(149 91 159 / var(--tw-bg-opacity)); -} - -.hover\:text-blue:hover{ - --tw-text-opacity: 1; - color: rgb(116 122 185 / var(--tw-text-opacity)); -} - -.hover\:text-classic-purple:hover{ - --tw-text-opacity: 1; - color: rgb(178 120 255 / var(--tw-text-opacity)); -} - -.hover\:text-purple:hover{ - --tw-text-opacity: 1; - color: rgb(149 91 159 / var(--tw-text-opacity)); -} - -.hover\:text-white:hover{ - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.hover\:underline:hover{ - text-decoration-line: underline; -} - -.focus\:border-classic-purple:focus{ - --tw-border-opacity: 1; - border-color: rgb(178 120 255 / var(--tw-border-opacity)); -} - -.focus\:outline-none:focus{ - outline: 2px solid transparent; - outline-offset: 2px; -} - -.focus\:ring-0:focus{ - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.focus\:ring-white:focus{ - --tw-ring-opacity: 1; - --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); -} - -.group:hover .group-hover\:inset-1{ - top: 0.25rem; - right: 0.25rem; - bottom: 0.25rem; - left: 0.25rem; -} - -.group:hover .group-hover\:translate-x-1{ - --tw-translate-x: 0.25rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -@keyframes shine{ - 100%{ - left: 125%; - } -} - -.group:hover .group-hover\:animate-shine{ - animation: shine 1s linear; -} - -.group:hover .group-hover\:opacity-75{ - opacity: 0.75; -} - -.group:hover .group-hover\:duration-200{ - transition-duration: 200ms; -} - -.peer:-moz-placeholder-shown ~ .peer-placeholder-shown\:translate-y-0{ - --tw-translate-y: 0px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:placeholder-shown ~ .peer-placeholder-shown\:translate-y-0{ - --tw-translate-y: 0px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:-moz-placeholder-shown ~ .peer-placeholder-shown\:scale-100{ - --tw-scale-x: 1; - --tw-scale-y: 1; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:placeholder-shown ~ .peer-placeholder-shown\:scale-100{ - --tw-scale-x: 1; - --tw-scale-y: 1; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:focus ~ .peer-focus\:left-0{ - left: 0px; -} - -.peer:focus ~ .peer-focus\:-translate-y-6{ - --tw-translate-y: -1.5rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:focus ~ .peer-focus\:scale-75{ - --tw-scale-x: .75; - --tw-scale-y: .75; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.peer:focus ~ .peer-focus\:text-gray-400{ - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} - -@media (min-width: 640px){ - .sm\:h-72{ - height: 18rem; - } -} - -@media (min-width: 768px){ - .md\:order-2{ - order: 2; - } - - .md\:m-0{ - margin: 0px; - } - - .md\:mx-0{ - margin-left: 0px; - margin-right: 0px; - } - - .md\:mx-2{ - margin-left: 0.5rem; - margin-right: 0.5rem; - } - - .md\:mx-32{ - margin-left: 8rem; - margin-right: 8rem; - } - - .md\:mx-auto{ - margin-left: auto; - margin-right: auto; - } - - .md\:mb-40{ - margin-bottom: 10rem; - } - - .md\:mr-0{ - margin-right: 0px; - } - - .md\:mt-0{ - margin-top: 0px; - } - - .md\:mt-16{ - margin-top: 4rem; - } - - .md\:mt-28{ - margin-top: 7rem; - } - - .md\:mt-4{ - margin-top: 1rem; - } - - .md\:mt-44{ - margin-top: 11rem; - } - - .md\:mt-6{ - margin-top: 1.5rem; - } - - .md\:inline-block{ - display: inline-block; - } - - .md\:flex{ - display: flex; - } - - .md\:hidden{ - display: none; - } - - .md\:h-\[230px\]{ - height: 230px; - } - - .md\:w-1\/4{ - width: 25%; - } - - .md\:w-96{ - width: 24rem; - } - - .md\:w-\[700px\]{ - width: 700px; - } - - .md\:w-auto{ - width: auto; - } - - .md\:w-max{ - width: -moz-max-content; - width: max-content; - } - - .md\:max-w-2xl{ - max-width: 42rem; - } - - .md\:max-w-sm{ - max-width: 24rem; - } - - .md\:max-w-xl{ - max-width: 36rem; - } - - .md\:flex-row{ - flex-direction: row; - } - - .md\:flex-col{ - flex-direction: column; - } - - .md\:items-start{ - align-items: flex-start; - } - - .md\:items-center{ - align-items: center; - } - - .md\:justify-start{ - justify-content: flex-start; - } - - .md\:justify-between{ - justify-content: space-between; - } - - .md\:justify-around{ - justify-content: space-around; - } - - .md\:space-x-8 > :not([hidden]) ~ :not([hidden]){ - --tw-space-x-reverse: 0; - margin-right: calc(2rem * var(--tw-space-x-reverse)); - margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); - } - - .md\:rounded-2xl{ - border-radius: 1rem; - } - - .md\:border-0{ - border-width: 0px; - } - - .md\:border-none{ - border-style: none; - } - - .md\:bg-transparent{ - background-color: transparent; - } - - .md\:p-0{ - padding: 0px; - } - - .md\:p-8{ - padding: 2rem; - } - - .md\:px-12{ - padding-left: 3rem; - padding-right: 3rem; - } - - .md\:px-16{ - padding-left: 4rem; - padding-right: 4rem; - } - - .md\:px-4{ - padding-left: 1rem; - padding-right: 1rem; - } - - .md\:px-8{ - padding-left: 2rem; - padding-right: 2rem; - } - - .md\:py-2{ - padding-top: 0.5rem; - padding-bottom: 0.5rem; - } - - .md\:pl-20{ - padding-left: 5rem; - } - - .md\:pr-7{ - padding-right: 1.75rem; - } - - .md\:pt-4{ - padding-top: 1rem; - } - - .md\:text-2xl{ - font-size: 1.5rem; - line-height: 2rem; - } - - .md\:text-4xl{ - font-size: 2.25rem; - line-height: 2.5rem; - } - - .md\:text-base{ - font-size: 1rem; - line-height: 1.5rem; - } - - .md\:text-lg{ - font-size: 1.125rem; - line-height: 1.75rem; - } - - .md\:text-sm{ - font-size: 0.875rem; - line-height: 1.25rem; - } - - .md\:text-xl{ - font-size: 1.25rem; - line-height: 1.75rem; - } -} - -@media (min-width: 1024px){ - .lg\:mx-44{ - margin-left: 11rem; - margin-right: 11rem; - } - - .lg\:my-10{ - margin-top: 2.5rem; - margin-bottom: 2.5rem; - } - - .lg\:flex{ - display: flex; - } - - .lg\:w-\[450px\]{ - width: 450px; - } - - .lg\:grid-cols-1{ - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .lg\:grid-cols-2{ - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .lg\:grid-cols-4{ - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .lg\:rounded-lg{ - border-radius: 0.5rem; - } - - .lg\:p-6{ - padding: 1.5rem; - } - - .lg\:py-6{ - padding-top: 1.5rem; - padding-bottom: 1.5rem; - } - - .lg\:text-3xl{ - font-size: 1.875rem; - line-height: 2.25rem; - } - - .lg\:text-base{ - font-size: 1rem; - line-height: 1.5rem; - } -} - -@media (min-width: 1280px){ - .xl\:max-w-lg{ - max-width: 32rem; - } - - .xl\:flex-row{ - flex-direction: row; - } - - .xl\:text-\[28px\]{ - font-size: 28px; - } - - .xl\:text-xl{ - font-size: 1.25rem; - line-height: 1.75rem; - } -} - -@media (min-width: 1536px){ - .\32xl\:mb-32{ - margin-bottom: 8rem; - } - - .\32xl\:mt-14{ - margin-top: 3.5rem; - } - - .\32xl\:mt-16{ - margin-top: 4rem; - } - - .\32xl\:mt-20{ - margin-top: 5rem; - } - - .\32xl\:mt-40{ - margin-top: 10rem; - } - - .\32xl\:max-w-3xl{ - max-width: 48rem; - } - - .\32xl\:max-w-4xl{ - max-width: 56rem; - } - - .\32xl\:max-w-screen-xl{ - max-width: 1280px; - } - - .\32xl\:max-w-xl{ - max-width: 36rem; - } - - .\32xl\:justify-center{ - justify-content: center; - } - - .\32xl\:p-0{ - padding: 0px; - } - - .\32xl\:text-2xl{ - font-size: 1.5rem; - line-height: 2rem; - } - - .\32xl\:text-4xl{ - font-size: 2.25rem; - line-height: 2.5rem; - } - - .\32xl\:text-base{ - font-size: 1rem; - line-height: 1.5rem; - } - - .\32xl\:text-lg{ - font-size: 1.125rem; - line-height: 1.75rem; - } - - .\32xl\:text-xl{ - font-size: 1.25rem; - line-height: 1.75rem; - } -} diff --git a/scripts/deploy.sh b/scripts/deploy.sh index abd76df..b2bb5ac 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -9,5 +9,4 @@ if [[ ! -f scripts/dark-cli-linux ]]; then fi -./scripts/dark-cli-linux public/ --canvas "${CANVAS}" --user "${USER}" --password "${PASSWORD}" - +./scripts/dark-cli-linux dist/ --canvas "${CANVAS}" --user "${USER}" --password "${PASSWORD}" diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..2f1f41e --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,63 @@ +import { BrowserRouter, Routes, Route } from "react-router-dom"; + +import ScrollToTop from "./common/utils/ScrollToTop"; +import Layout from "./common/layout/Layout"; + +import Home from "./pages/Home"; + +import Classic from "./pages/Classic"; +import ClassicSignup from "./pages/Classic/Signup"; + +import Language from "./pages/Language" +import CLI from "./pages/CLI"; +import Backends from "./pages/Backends"; +import AI from "./pages/AI" +import Distribution from "./pages/Distribution" +import Execution from "./pages/Execution" +import TraceDriven from "./pages/TraceDriven" +import TypeChecking from "./pages/TypeChecking" + +import Roadmap from "./pages/Roadmap"; +import Company from "./pages/Company"; +import GettingStarted from "./pages/GettingStarted"; +import ForX from "./pages/For" +import Cloud from "./pages/Cloud"; + +import NotFound from "./pages/NotFound"; +import Editing from "./pages/Home/Editing"; + +function App() { + return ( + + + + }> + } /> + + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + + } /> + + + + ); +} + +export default App; diff --git a/src/assets/John_Constable_-_The_Hay_Wain_-1821-.jpg b/src/assets/John_Constable_-_The_Hay_Wain_-1821-.jpg new file mode 100644 index 0000000..8fd6f6c Binary files /dev/null and b/src/assets/John_Constable_-_The_Hay_Wain_-1821-.jpg differ diff --git a/src/assets/The_Sower-1.jpg b/src/assets/The_Sower-1.jpg new file mode 100644 index 0000000..b8fc1fa Binary files /dev/null and b/src/assets/The_Sower-1.jpg differ diff --git a/src/assets/cli.png b/src/assets/cli.png new file mode 100644 index 0000000..098fe7a Binary files /dev/null and b/src/assets/cli.png differ diff --git a/public/img/dark-classic.png b/src/assets/dark-classic-toplevel.png similarity index 100% rename from public/img/dark-classic.png rename to src/assets/dark-classic-toplevel.png diff --git a/public/img/darklang-classic.png b/src/assets/darklang-classic.png similarity index 100% rename from public/img/darklang-classic.png rename to src/assets/darklang-classic.png diff --git a/src/assets/darklang-cli-ascii.png b/src/assets/darklang-cli-ascii.png new file mode 100644 index 0000000..d178412 Binary files /dev/null and b/src/assets/darklang-cli-ascii.png differ diff --git a/public/img/wordmark-dark-transparent.png b/src/assets/darklang-logo-dbg.png similarity index 100% rename from public/img/wordmark-dark-transparent.png rename to src/assets/darklang-logo-dbg.png diff --git a/src/assets/darklang-logo-framed.png b/src/assets/darklang-logo-framed.png new file mode 100644 index 0000000..60ec9d7 Binary files /dev/null and b/src/assets/darklang-logo-framed.png differ diff --git a/src/assets/darklang-logo.png b/src/assets/darklang-logo.png new file mode 100644 index 0000000..3324e60 Binary files /dev/null and b/src/assets/darklang-logo.png differ diff --git a/src/assets/double-grid-square.png b/src/assets/double-grid-square.png new file mode 100644 index 0000000..d6ee1d3 Binary files /dev/null and b/src/assets/double-grid-square.png differ diff --git a/src/assets/double-grid.png b/src/assets/double-grid.png new file mode 100644 index 0000000..67af968 Binary files /dev/null and b/src/assets/double-grid.png differ diff --git a/src/assets/editing2.png b/src/assets/editing2.png new file mode 100644 index 0000000..0969604 Binary files /dev/null and b/src/assets/editing2.png differ diff --git a/src/assets/editing3.png b/src/assets/editing3.png new file mode 100644 index 0000000..465e0be Binary files /dev/null and b/src/assets/editing3.png differ diff --git a/src/assets/github-logo-white.png b/src/assets/github-logo-white.png new file mode 100644 index 0000000..fe7e299 Binary files /dev/null and b/src/assets/github-logo-white.png differ diff --git a/src/assets/github-logo.png b/src/assets/github-logo.png new file mode 100644 index 0000000..9490ffc Binary files /dev/null and b/src/assets/github-logo.png differ diff --git a/src/assets/grid.png b/src/assets/grid.png new file mode 100644 index 0000000..362e7e5 Binary files /dev/null and b/src/assets/grid.png differ diff --git a/src/assets/logo-ascii.png b/src/assets/logo-ascii.png new file mode 100644 index 0000000..ae130e0 Binary files /dev/null and b/src/assets/logo-ascii.png differ diff --git a/src/assets/murmuration.webp b/src/assets/murmuration.webp new file mode 100644 index 0000000..6310e45 Binary files /dev/null and b/src/assets/murmuration.webp differ diff --git a/src/assets/packageManager.png b/src/assets/packageManager.png new file mode 100644 index 0000000..f315286 Binary files /dev/null and b/src/assets/packageManager.png differ diff --git a/src/common/Banner.tsx b/src/common/Banner.tsx new file mode 100644 index 0000000..d643dad --- /dev/null +++ b/src/common/Banner.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +interface BannerProps { + text: string; +} + +const Banner: React.FC = ({ text }) => { + return ( +
+ + + + + {text}.{" "} + + See our roadmap → + + +
+ ); +}; + +export default Banner; diff --git a/src/common/layout/Footer.tsx b/src/common/layout/Footer.tsx new file mode 100644 index 0000000..947d126 --- /dev/null +++ b/src/common/layout/Footer.tsx @@ -0,0 +1,315 @@ +import { Link } from "react-router-dom"; + +import darkLangLogo from "~/assets/darklang-logo.png"; +import darkLangLogoDark from "~/assets/darklang-logo-dbg.png"; + +// Define valid page types +type PageName = + | "home" + | "classic" + | "classic/signup" + | "roadmap" + | "cli" + | "editing" + | string; + +interface FooterProps { + currentPage: PageName; +} + +const Footer = ({ currentPage }: FooterProps) => { + // Define background colors for different pages + const bgColors: Record = { + home: "bg-white", + "classic": "bg-dark text-white", + "classic/signup": "bg-dark text-white", + roadmap: "bg-white", + cli: "bg-dark text-white", + editing: "bg-dark text-white", + // Default for any other page (like NotFound) + default: "bg-white", + }; + + // Get the color for the current page, or use default if not defined + const bgColor = bgColors[currentPage] || bgColors.default; + // Determine if we're using a dark background + const isDarkBg = bgColor.includes("bg-dark"); + + const logoSrc = isDarkBg ? darkLangLogoDark : darkLangLogo; + + return ( + + ); +}; + +export default Footer; diff --git a/src/common/layout/Header.tsx b/src/common/layout/Header.tsx new file mode 100644 index 0000000..15e0a6c --- /dev/null +++ b/src/common/layout/Header.tsx @@ -0,0 +1,381 @@ +/** + * Header Component + */ + +import { Link } from "react-router-dom"; +import { useState } from "react"; +import darkLangLogo from "~/assets/darklang-logo.png"; +import darkLangLogoDark from "~/assets/darklang-logo-dbg.png"; +import githubLogo from "~/assets/github-logo.png"; +import githubLogoWhite from "~/assets/github-logo-white.png"; +import Dropdown from "../ui/Dropdown"; + +type PageName = "home" | "classic" | "classic-signup" | "roadmap" | "cli" | string; + +interface HeaderProps { + currentPage: PageName; +} + +const Header = ({ currentPage }: HeaderProps) => { + // Define background colors for different pages + const bgColors: Record = { + home: "bg-white", + "classic": "bg-dark text-white", + "classic/signup": "bg-dark text-white", + roadmap: "bg-white", + cli: "bg-dark text-white", + editing: "bg-dark text-white", + // Default for any other page (like NotFound) + default: "bg-white", + }; + + // Get the color for the current page, or use default if not defined + const bgColor = bgColors[currentPage] || bgColors.default; + + const isDarkBg = bgColor.includes("bg-dark"); + + const logoSrc = isDarkBg ? darkLangLogoDark : darkLangLogo; + const githubLogoSrc = isDarkBg ? githubLogoWhite : githubLogo; + + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); + + const toggleMobileMenu = () => { + setIsMobileMenuOpen(!isMobileMenuOpen); + }; + + return ( +
+
+ + Darklang Logo + + + + {/* Burger Menu Button (mobile only) */} + +
+ + {/* Mobile Menu */} + {isMobileMenuOpen && ( +
+ +
+ )} +
+ ); +}; + +export default Header; diff --git a/src/common/layout/Layout.tsx b/src/common/layout/Layout.tsx new file mode 100644 index 0000000..10babba --- /dev/null +++ b/src/common/layout/Layout.tsx @@ -0,0 +1,34 @@ +import { Outlet, useLocation } from "react-router-dom"; + +import Header from "./Header"; +import Footer from "./Footer"; +import Banner from "../Banner"; + +const Layout = () => { + // Get current location to determine the active page + const location = useLocation(); + const currentPage = location.pathname.substring(1) || "home"; + + // Use bg-dark for CLI page, otherwise transparent + const bgClass = currentPage === "cli" ? "bg-dark" : "bg-transparent"; + + return ( +
+
+ { + currentPage.startsWith('classic') + ? <> + : + } + +
+
+
+ +
+
+
+ ); +}; + +export default Layout; diff --git a/src/common/ui/BlogPostCard/BlogPostCard.tsx b/src/common/ui/BlogPostCard/BlogPostCard.tsx new file mode 100644 index 0000000..8a70c70 --- /dev/null +++ b/src/common/ui/BlogPostCard/BlogPostCard.tsx @@ -0,0 +1,45 @@ +import React from "react"; + +interface BlogPostCardProps { + author: string; + date: string; + title: string; + excerpt: string; + imageUrl: string; + slug: string; +} + +export const BlogPostCard: React.FC = ({ + author, + date, + title, + excerpt, + imageUrl, + slug, +}) => { + return ( +
+ +
+
+ By {author} + {date} +
+

{title}

+

+ {excerpt} +

+
+
+ {title} +
+
+
+ ); +}; + +export default BlogPostCard; diff --git a/src/common/ui/BlogPostCard/index.ts b/src/common/ui/BlogPostCard/index.ts new file mode 100644 index 0000000..9c69e81 --- /dev/null +++ b/src/common/ui/BlogPostCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./BlogPostCard"; +export * from "./BlogPostCard"; diff --git a/src/common/ui/Button.tsx b/src/common/ui/Button.tsx new file mode 100644 index 0000000..d66a6e6 --- /dev/null +++ b/src/common/ui/Button.tsx @@ -0,0 +1,44 @@ +/** + * Button Component + * A reusable button component with different variants and sizes. + */ + +import React from "react"; + +type ButtonProps = { + variant?: "primary" | "secondary" | "outline"; + size?: "sm" | "md" | "lg"; + children: React.ReactNode; +} & React.ButtonHTMLAttributes; + +const Button = ({ + variant = "primary", + size = "md", + children, + className = "", + ...props +}: ButtonProps) => { + let baseClasses = "rounded font-medium transition-colors focus:outline-none"; + + const variantClasses = { + primary: "bg-blue-600 text-white hover:bg-blue-700", + secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300", + outline: "border bg-transparent hover:bg-gray-100", + }; + + const sizeClasses = { + sm: "px-2 py-1 text-sm", + md: "px-4 py-2", + lg: "px-6 py-3", + }; + + const buttonClasses = `${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`; + + return ( + + ); +}; + +export default Button; diff --git a/src/common/ui/CTASection/index.tsx b/src/common/ui/CTASection/index.tsx new file mode 100644 index 0000000..8875528 --- /dev/null +++ b/src/common/ui/CTASection/index.tsx @@ -0,0 +1,41 @@ +/** + * CallToAction component + */ + +import React, { ReactNode } from "react"; + +interface CTASectionProps { + children: ReactNode; + className?: string; +} + +const CTASection: React.FC = ({ + children, + className = "", +}) => { + return ( +
+ {/* Relative container to position the intersecting corner lines and content */} +
+ {/* Full horizontal lines that cross the entire container */} +
+
+ +
+
+ + {/* Full vertical lines that cross the entire container */} +
+
+ +
+
+ + {/* Content */} +
{children}
+
+
+ ); +}; + +export default CTASection; diff --git a/src/common/ui/Card/TraceCard.tsx b/src/common/ui/Card/TraceCard.tsx new file mode 100644 index 0000000..6164af9 --- /dev/null +++ b/src/common/ui/Card/TraceCard.tsx @@ -0,0 +1,96 @@ +/** + * TraceCard Component + * A card component for displaying trace information + */ + +import React from "react"; + +interface TraceCardProps { + title: string; + icon?: React.ReactNode; + description: string; + codeSample?: string; + className?: string; + color?: "blue" | "purple" | "magenta" | "orange" | "gray" | "taupe"; +} + +const TraceCard: React.FC = ({ + title, + icon, + description, + codeSample, + className = "", + color = "blue", +}) => { + // Map colors to tailwind classes + const colorMap = { + blue: { + title: "text-blue-500", + icon: "bg-blue-100", + code: "bg-blue-50", + }, + purple: { + title: "text-blue-lbg", + icon: "bg-indigo-100", + code: "bg-indigo-50", + }, + magenta: { + title: "text-purple-lbg", + icon: "bg-purple-lbg/10", + code: "bg-purple-lbg/10", + }, + orange: { + title: "text-tan", + icon: "bg-orange-100", + code: "bg-orange-50", + }, + taupe: { + title: "text-taupe", + icon: "bg-taupe/30", + code: "bg-taupe/30", + }, + gray: { + title: "text-gray-500", + icon: "bg-gray-200", + code: "bg-gray-50", + }, + }; + + const colorClasses = colorMap[color]; + + return ( +
+
+ {icon && ( +
+ {icon} +
+ )} +
+ +

+ {title} +

+ +
{description}
+ + {codeSample && ( +
+
+            {codeSample}
+          
+
+ )} +
+ ); +}; + +export default TraceCard; diff --git a/src/common/ui/Card/index.ts b/src/common/ui/Card/index.ts new file mode 100644 index 0000000..9c5f42f --- /dev/null +++ b/src/common/ui/Card/index.ts @@ -0,0 +1 @@ +export { default as TraceCard } from "./TraceCard"; diff --git a/src/common/ui/CodeDisplay.tsx b/src/common/ui/CodeDisplay.tsx new file mode 100644 index 0000000..983efc6 --- /dev/null +++ b/src/common/ui/CodeDisplay.tsx @@ -0,0 +1,52 @@ +import React, { useState, useEffect } from "react"; +import hljs from "highlight.js/lib/core"; +import "highlight.js/styles/vs2015.min.css"; +import fsharp from "highlight.js/lib/languages/fsharp"; + +hljs.registerLanguage("fsharp", fsharp); + +interface CodeDisplayProps { + code: string; + language?: string; + showLineNumbers?: boolean; +} + +const CodeDisplay: React.FC = ({ + code, + language = "fsharp", + showLineNumbers = true, +}) => { + const [highlightedCode, setHighlightedCode] = useState(""); + + useEffect(() => { + const highlighted = hljs.highlight(code, { language }).value; + + const codeLines = highlighted.split("\n"); + + const codeWithLineNumbers = codeLines + .map((line, index) => { + const lineNumber = index + 1; + return `
${ + showLineNumbers + ? `${lineNumber}` + : "" + }${line || " "}
`; + }) + .join(""); + + setHighlightedCode(codeWithLineNumbers); + }, [code, language, showLineNumbers]); + + return ( +
+
+        
+      
+
+ ); +}; + +export default CodeDisplay; diff --git a/src/common/ui/CodeEditor/CompletionMenu.tsx b/src/common/ui/CodeEditor/CompletionMenu.tsx new file mode 100644 index 0000000..3010d50 --- /dev/null +++ b/src/common/ui/CodeEditor/CompletionMenu.tsx @@ -0,0 +1,43 @@ +/** + * CompletionMenu Component + * A dropdown menu for code completion suggestions + */ + +import React from "react"; + +interface CompletionItem { + label: string; + description?: string; +} + +interface CompletionMenuProps { + items: CompletionItem[]; +} + +const CompletionMenu: React.FC = ({ items }) => { + return ( +
+
    + {items.map((item, index) => ( +
  • +
    + {item.label} + {item.description && ( + + {item.description} + + )} +
    +
  • + ))} +
+
+ ); +}; + +export default CompletionMenu; diff --git a/src/common/ui/CodeEditor/index.tsx b/src/common/ui/CodeEditor/index.tsx new file mode 100644 index 0000000..ed9d0c9 --- /dev/null +++ b/src/common/ui/CodeEditor/index.tsx @@ -0,0 +1,213 @@ +/** + * CodeEditor Component + */ + +import React, { useState, useEffect } from "react"; +import CodeDisplay from "../CodeDisplay"; +import hljs from "highlight.js/lib/core"; +import "highlight.js/styles/vs2015.min.css"; +import fsharp from "highlight.js/lib/languages/fsharp"; + +hljs.registerLanguage("fsharp", fsharp); + +interface CodeEditorProps { + code: string; + language?: string; + showCompletion?: boolean; + showHover?: boolean; + showDiagnostics?: boolean; + showGoToDef?: boolean; +} + +const CodeEditor: React.FC = ({ + code, + language = "fsharp", + showCompletion = false, + showHover = false, + showDiagnostics = false, + showGoToDef = false, +}) => { + const [highlightedCode, setHighlightedCode] = useState< + Array<{ html: string }> + >([]); + + // Create line numbers + const lines = code.split("\n"); + const lineNumbers = Array.from( + { length: Math.max(7, lines.length) }, + (_, i) => i + 1, + ); + + useEffect(() => { + const processedLines = lines.map(line => { + if (line.trim() === "") return { html: " " }; + const highlighted = hljs.highlight(line, { language }).value; + return { html: highlighted }; + }); + + setHighlightedCode(processedLines); + }, [code, language]); + + return ( +
+ {/* Editor top bar with dots */} +
+
+
+
+
+
+
+ + {/* Code area */} +
+
+ {/* Line numbers */} +
+ {lineNumbers.map(num => ( +
+ {num} +
+ ))} +
+ + {/* Actual code with syntax highlighting */} +
+ {highlightedCode.map((line, index) => ( +
+ +
+ ))} + {renderEmptyLines(Math.max(0, 7 - lines.length))} +
+
+ + {/* Code completion dropdown */} + {showCompletion && ( +
+
    +
  • +
    + empty +
    +
  • +
  • +
    + toArray +
    +
  • +
  • +
    + map +
    +
  • +
  • +
    + filter +
    +
  • +
  • +
    + length +
    +
  • +
  • +
    + forEach +
    +
  • +
  • +
    + foldr +
    +
  • +
  • +
    + foldl +
    +
  • +
+
+ )} + + {/* Hover info */} + {showHover && ( +
+
+
List.empty
+
+ Create an empty list of any type +
+
a' list
+
+
+ )} + + {/* Diagnostics error */} + {showDiagnostics && ( +
+
+
+
Error
+
+ Cannot use List without completing the method call +
+
+
+ )} + + {/* Go to definition - Popup with function definition */} + {showGoToDef && ( + <> + {/* Underline the function name */} +
+ + {/* Small popup showing function definition */} +
+
+
+ {/* Popup header */} +
+
+
+
+
+
+
+ darklang/packages/stdlib/List.dark +
+
+ + {/* Code content */} + +
+
+ + )} +
+
+ ); +}; + +// Render empty lines to fill space +const renderEmptyLines = (count: number) => { + return Array.from({ length: count }, (_, i) => ( +
+   +
+ )); +}; + +export default CodeEditor; diff --git a/src/common/ui/Dropdown.tsx b/src/common/ui/Dropdown.tsx new file mode 100644 index 0000000..935df79 --- /dev/null +++ b/src/common/ui/Dropdown.tsx @@ -0,0 +1,87 @@ +import React, { useState, useRef, useEffect } from "react"; +import { Link } from "react-router-dom"; + +interface DropdownProps { + label: string; + labelColor?: string; + items: { + text: string; + href: string; + target?: string; + }[]; +} + +const Dropdown: React.FC = ({ label, labelColor, items }) => { + const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); + + const toggleDropdown = () => { + setIsOpen(!isOpen); + }; + + // Close dropdown when clicking outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + + return ( +
+ + + {isOpen && ( +
+
+ {items.map((item, index) => ( + + setIsOpen(false)} + > + {item.text} + + {index < items.length - 1 && ( +
+ )} +
+ ))} +
+
+ )} +
+ ); +}; + +export default Dropdown; diff --git a/src/common/ui/Icons/FeatureIcons.tsx b/src/common/ui/Icons/FeatureIcons.tsx new file mode 100644 index 0000000..0eb4928 --- /dev/null +++ b/src/common/ui/Icons/FeatureIcons.tsx @@ -0,0 +1,105 @@ +/** + * FeatureIcons + * Icons for feature cards and other UI elements + */ + +import React from "react"; + +interface IconProps { + className?: string; +} + +export const HttpIcon: React.FC = () => ( + + + +); + +export const WorkerIcon: React.FC = () => ( + + + + + + +); + +export const CronIcon: React.FC = () => ( + + + + +); + +export const FnIcon: React.FC = () => ( + + + +); + +export const CliIcon: React.FC = () => ( + + + +); + +export const MiscIcon: React.FC = () => ( + + + + + +); diff --git a/src/common/ui/Icons/index.ts b/src/common/ui/Icons/index.ts new file mode 100644 index 0000000..23d4ad5 --- /dev/null +++ b/src/common/ui/Icons/index.ts @@ -0,0 +1 @@ +export * from "./FeatureIcons"; diff --git a/src/common/ui/SectionTitle.tsx b/src/common/ui/SectionTitle.tsx new file mode 100644 index 0000000..c28fae9 --- /dev/null +++ b/src/common/ui/SectionTitle.tsx @@ -0,0 +1,65 @@ +/** + * SectionTitle Component + * A reusable component for section titles + */ + +import React, { ReactNode } from "react"; + +interface SectionTitleProps { + subtitle?: string; + children: ReactNode; + description?: string; + align?: "left" | "center" | "right"; + className?: string; + maxWidth?: string; + textColor?: string; + subtitleStyle?: "text" | "button"; +} + +const SectionTitle: React.FC = ({ + subtitle, + children, + description, + align = "left", + className = "", + maxWidth = "max-w-6xl", + textColor, + subtitleStyle = "text", +}) => { + const textAlignment = { + left: "text-left", + center: "text-center", + right: "text-right", + }[align]; + + return ( +
+ {subtitle && + (subtitleStyle === "button" ? ( +
+ +
+ ) : ( +
+ {subtitle} +
+ ))} +

+ {children} +

+ {description && ( +

+ {description} +

+ )} +
+ ); +}; + +export default SectionTitle; diff --git a/src/common/ui/Terminal.tsx b/src/common/ui/Terminal.tsx new file mode 100644 index 0000000..45c18ff --- /dev/null +++ b/src/common/ui/Terminal.tsx @@ -0,0 +1,30 @@ +/** + * Terminal Component + * Renders a terminal-like UI with customizable content + */ + +import React, { ReactNode } from "react"; + +interface TerminalProps { + children: ReactNode; + className?: string; +} + +const Terminal: React.FC = ({ children, className = "" }) => { + return ( +
+
+
+
+
+
+
+
+
+ {children} +
+
+ ); +}; + +export default Terminal; diff --git a/src/common/utils/ScrollToTop.tsx b/src/common/utils/ScrollToTop.tsx new file mode 100644 index 0000000..46e6144 --- /dev/null +++ b/src/common/utils/ScrollToTop.tsx @@ -0,0 +1,14 @@ +import { useEffect } from "react"; +import { useLocation } from "react-router-dom"; + +function ScrollToTop() { + const { pathname } = useLocation(); + + useEffect(() => { + window.scrollTo(0, 0); + }, [pathname]); + + return null; +} + +export default ScrollToTop; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..bd3ecdb --- /dev/null +++ b/src/index.css @@ -0,0 +1,76 @@ +@import "tailwindcss"; + +body { + font-family: "Quicksand", sans-serif; + overflow-x: hidden; +} + +.code-with-line-numbers { + font-family: monospace; + white-space: pre; +} + +.code-line { + display: flex; + width: 100%; + min-height: 1.2em; +} + +.line-number { + display: inline-block; + width: 2rem; + text-align: right; + padding-right: 1rem; + margin-right: 1rem; + color: #888; + /* border-right: 1px solid #ddd; */ +} + +.line-content { + flex: 1; + white-space: pre-wrap; + line-height: 1.3; +} + +@theme { + /* Classic editor colors */ + --color-dark: #2f2f2f; + --color-dark-black: #1e1e1e; + --color-gray-custom: #484848; + --color-gray-dark: #8b8888; + --color-gray-light: #a8a8a8; + --color-rust: #bf6360; + --color-taupe: #a1887f; + --color-sand: #f7ca88; + --color-mint: #86c1b9; + --color-rose: #d5839d; + --color-olive: #a1b56c; + --color-tan: #dc9656; + --color-lavender: #c7abcd; + + /* Darklang colors */ + --color-black-custom: #2f2f2f; + /* --color-white-custom: #F8F8F8; */ + --color-white-custom: #ffffff; + + /* Define purple and blue with their variations */ + --color-purple-dbg: #8f5ea1; + --color-purple-lbg: #95589f; + /*lighter purple*/ + --color-purple-secondry: #a76bba; + + --color-blue-dbg: #6d74c5; + --color-blue-lbg: #747ab9; + + --color-dark-gray: #2f2f2f; + --color-classic-green: #a1b56c; + --color-classic-brown: #a1887f; + --color-classic-yellow: #e6bd81; + --color-classic-blue: #86c1b9; + --color-classic-purple: #b278ff; + --color-classic-pink: #f56ff0; + + --font-caveat: Caveat, cursive; + --font-sans: Quicksand, sans-serif; + --font-code: Fira Code, monospace; +} diff --git a/src/input.css b/src/input.css deleted file mode 100644 index 45d5052..0000000 --- a/src/input.css +++ /dev/null @@ -1,11 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=League+Gothic&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Assistant:wght@700&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Assistant:wght@700&family=Fira+Code:wght@400;500;600&display=swap"); -@tailwind base; -@tailwind components; -@tailwind utilities; - -.hljs-title.hljs-title { - @apply text-red-800; -} diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..abf3265 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,11 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; + +import "./index.css"; +import App from "./App.tsx"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/src/pages/AI/index.tsx b/src/pages/AI/index.tsx new file mode 100644 index 0000000..62ae2ed --- /dev/null +++ b/src/pages/AI/index.tsx @@ -0,0 +1,35 @@ +import React from "react"; + +const AI: React.FC = () => { + return ( +
+## Generally
+
+## For your development
+- very generous parser
+- import/export to other languages using AI
+- support copilot
+- redesigned to support AI
+- bring-your-own-model
+
+
+## For your users
+
+
+- (bullets from "designed for GenAI")
+- "built for AI"
+- build vendor SDKs automagically
+- prompt using your AI, or ours
+- build AI models in darklang
+- agents
+- packages for integrating with OpenAI or other models
+- support for local whatever
+- future: native support for vector DBs?
+- alternative to langchain
+	- prompt pipelines, etc
+
+	
+ ); +}; + +export default AI; diff --git a/src/pages/Backends/index.tsx b/src/pages/Backends/index.tsx new file mode 100644 index 0000000..e9719f0 --- /dev/null +++ b/src/pages/Backends/index.tsx @@ -0,0 +1,72 @@ +import React from "react"; + +const Backends: React.FC = () => { + return ( +
+
+        talk about features
+        http handlers
+        CRONs
+        workers
+        etc.
+
+        talk about our cloud offerings
+        reference things in dark-classic
+
+        talk about eventual migration from -classic to -next
+      
+ +
+ +

+ Darklang is a programming language and platform designed to simplify backend development by removing much of the complexity associated with traditional backend infrastructure. Its backend features are tightly integrated into a single environment, and built to streamline the creation of cloud-native applications without managing infrastructure, deployments, or containers. +

+ +
+

Darklang’s backend features—HTTP handlers, scheduled jobs (CRONs), background workers, and datastores are designed for rapid development and prototyping, with a focus on simplicity and instant deployment.

+ +
+

+ Datastores: + - Datastores in Darklang are key-value stores used for persistent data storage, integrated seamlessly with handlers and workers. + - when you set up a database in dark, you just add the database, like you click a button or a keyboard shortcut, no requiring a server from somewhere to put it on, no going to another server, no config, no orm it is written in the same language as the rest of your code + - when you make a query, you query in the dark + + talk about operations? + - (DB.set, DB.get...) + - (DB.query...) +

+ +
+ +

+ HTTP Handlers: + - HTTP handlers in Darklang are the core mechanism for handling incoming HTTP requests, serving as the entry point for API endpoints and web applications. + - when setting up a HTTP request you're not setting up a HTTP server, you're just add an end point that is directly connected to the code and you write them in the same place. There's no spinning up servers + - Darklang is designed for interacting with 3rd party APIs over HTTP. The `HttpClient` module has a set of functions for calling out to other HTTP services and APIs +

+
+ +

+ Scheduled jobs: + - CRON jobs in Darklang are scheduled tasks that run on a predefined schedule, similar to Unix cron, ideal for periodic tasks like report generation or data cleanup. + - Crons run automatically once per interval +

+ +
+

+ Background Workers: + - Workers in Darklang handle asynchronous background tasks, processing messages from a queue, making them ideal for tasks like API calls, batch processing, or report generation. + - Darklang supports doing work asynchronously outside the context of an HTTP handler using a **Worker**. Each worker has a queue of messages, which are processed loosely in-order, executing the code within the Worker once for each message. Messages are created by calling `emit` from any other code, and can contain arbitrary event data. + + ADD Example use case? +

+
+ +
+ + + ); +}; + +export default Backends; diff --git a/src/pages/CLI/index.tsx b/src/pages/CLI/index.tsx new file mode 100644 index 0000000..92fffb6 --- /dev/null +++ b/src/pages/CLI/index.tsx @@ -0,0 +1,397 @@ +import React from "react"; + +import cliImage from "~/assets/cli.png"; +import doubleGridImage from "~/assets/double-grid.png"; +import gridImage from "~/assets/grid.png"; +import logoAscii from "~/assets/logo-ascii.png"; +import cliAscii from "~/assets/darklang-cli-ascii.png"; + +import Terminal from "../../common/ui/Terminal.tsx"; +import Button from "../../common/ui/Button.tsx"; +import CTASection from "../../common/ui/CTASection/index.tsx"; + +const CLIPage: React.FC = () => { + return ( +
+ {/* ASCII Art Header Section - Hidden on Mobile */} +
+
+ Darklang CLI ASCII +
+
+ + {/* CLI Platform Section */} +
+
+
+
+ $ darklang platform | +
+

+ Darklang's CLI is fully cross-platform, seamlessly running on + macOS, Linux, and Windows for a consistent development experience + everywhere +

+ +
+
+ Darklang CLI Terminal +
+
+
+ + {/* Get Started Section */} +
+
+ $ darklang get started | +
+
+ + {/* Bash Complexities Section */} +
+
+ $ darklang solving bash complexities | +
+ +
+
+

+ Darklang CLI is a better replacement for traditional file-based + scripts, such as in bash, python, lua, js, etc. +

+ +

+ bash is super hard to read, using weird variable names. While lots + of us can read and write bash scripts, since there are few + experts, it's not a great language. +

+ +
    +
  • + - + + lack of a package manager means the generated code has to use + cli tools, which each have different interfaces, which may not + be installed, and are often opaque + +
  • + +
  • + - + + different versions of the tools might be installed with subtly + different behaviour (esp gnu vs bsd) + +
  • + +
  • + - + + lack of real types and functions (which are a mess in bash) + contributes to these problems + +
  • +
+
+
+ grid +
+
+
+ + {/* Darklang for Scripts Section */} +
+
+ $ darklang for your scripts | +
+
+ grid +
+

+ Darklang is used as a better language for scripts: +

+ +
    +
  • + - + + Static types help ensure correctness + +
  • + +
  • + - + + Immutable values make code easier to understand and verify + +
  • + +
  • + - + + Built-in package manager + +
  • + +
  • + + + without an npm install step + +
  • + +
  • + + + versioned immutable functions and packages + +
  • + +
  • + - + + Easy to take a script and move it to the cloud + +
  • + +
  • + - + + Easy to use traces + +
  • + +
  • + - + + Easy to test, and be sure it's working + +
  • +
+
+
+
+ + {/* Darklang Examples Section */} +
+
+ $ darklang examples | +
+
+ {/* Left Terminal */} + +
+ $ + curl + https://darklang.com/download + | + bash +
+ +
+ Darklang installed in{" "} + ~/.darklang/bin/darklang +
+ +
+ Add to + PATH + via .bashrc + [y, n, ?]: + y +
+ +
+ + Added to .bashrc. +
+ +
Next you can:
+

# Try the tutorial

+

darklang tutorial

+

+ # Run some code from the package manager darklang +

+

@paul.fizzbuzz 3

+

# Generate some code

+

+ darklang prompt{" "} + + "Find ts scripts with more than 600 lines which use the commonjs + format" + +

+

+ # See available command line options +

+

darklang help

+
+ + {/* Right Column */} +
+ +
+ $ + darklang + @paul.fizzbuzz 3 +
+
1
+
2
+
Fizz
+
+ + +
+ $ + darklang + + deploy @paul.fizzbuzz /fizzbuzz + +
+ +
+ {" "} + Deployed to{" "} + https://furry-squirrel-3562.darklang.io/fizzbuzz +
+
+ in + 0.135s +
+
+ + +
+ $ curl -sSO + + https://furry-squirrel-3562.darklang.io/fizzbuzz/3 + +
+
1
+
2
+
Fizz
+
+
+
+ logo-ascii +
+ + {/* Darklang Commands Section */} +
+
+ $ darklang commands | +
+ +
+
+
+ dark help +
+
+ Show this help message and exit +
+
+ +
+
+ dark [function name] +
+
+ Run a function in the package manager i.e. `dark + @Darklang.Stdlib.Bool.not true` +
+
+ +
+
+ dark run [script path] +
+
+ Run a .dark script i.e. `dark ./my-script.dark` +
+
+ +
+
+ dark install +
+
+ Install the darklang CLI so it's available globally in your + terminal +
+
+ +
+
+ dark http +
+
+ Lists both local and cloud handlers +
+
+ +
+
+ dark dbs +
+
+ Lists both local and cloud dbs +
+
+
+ +
+ +
+
+ + +
+

+ Getting Started with Darklang CLI +

+

+ Write your first script in Darklang today and have it running in + minutes +

+ +
+
+
+ ); +}; + +export default CLIPage; diff --git a/src/pages/Classic/Signup.tsx b/src/pages/Classic/Signup.tsx new file mode 100644 index 0000000..ab83907 --- /dev/null +++ b/src/pages/Classic/Signup.tsx @@ -0,0 +1,243 @@ +import { useState, FormEvent } from "react"; +import { Link } from "react-router-dom"; + +import darklangClassic from "~/assets/darklang-classic.png"; + +const Signup = () => { + const [errors, setErrors] = useState([]); + const [showError, setShowError] = useState(false); + const [showSuccess, setShowSuccess] = useState(false); + + const clearErrors = () => { + setErrors([]); + setShowError(false); + }; + + const displayErrors = (errorMessages: string[]) => { + clearErrors(); + setErrors(errorMessages); + setShowError(true); + }; + + const displaySuccess = () => { + clearErrors(); + setShowSuccess(true); + }; + + const handleSubmit = async (event: FormEvent) => { + event.preventDefault(); + + // Reset both error and success states + clearErrors(); + setShowSuccess(false); + + const form = event.currentTarget; + const codeOfConductInput = form.querySelector( + "#code-of-conduct", + ) as HTMLInputElement; + + if (!codeOfConductInput.checked) { + displayErrors(["Please agree to our code of conduct"]); + return; + } + + const nameInput = form.querySelector("#name") as HTMLInputElement; + const emailInput = form.querySelector("#email") as HTMLInputElement; + const usernameInput = form.querySelector("#username") as HTMLInputElement; + + const data = { + name: nameInput.value, + email: emailInput.value.toLowerCase(), + username: usernameInput.value, + }; + + try { + const response = await fetch( + "https://ops-adduser.builtwithdark.com/v3/create-account", + { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }, + ); + + if (response.status === 200) { + form.reset(); + displaySuccess(); + } else { + const errorText = await response.text(); + displayErrors([errorText]); + } + } catch (error) { + displayErrors(["An error occurred. Please try again later."]); + console.error("Signup error:", error); + } + }; + + return ( +
+
+
+ Darklang Classic +

+ We're currently focused on the{" "} + + next{" "} + + version of Darklang, but you can still try Darklang Classic! +

+
+ +
+ {/* Error display */} + {showError && !showSuccess && ( +
+
    + {errors.map((error, index) => ( +
  • {error}
  • + ))} +
+
+ )} + + {/* Success message */} +
+

+ Successfully signed up! +

+

+ Thank you for signing up. Check your email for further + instructions. +

+
+ + {!showSuccess && ( +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ )} +
+ +

+ Already have an account?{" "} + + Log in + +

+
+
+ ); +}; + +export default Signup; diff --git a/src/pages/Classic/index.tsx b/src/pages/Classic/index.tsx new file mode 100644 index 0000000..4015275 --- /dev/null +++ b/src/pages/Classic/index.tsx @@ -0,0 +1,214 @@ +import darklangClassic from "~/assets/darklang-classic.png"; +import darkClassicToplevel from "~/assets/dark-classic-toplevel.png"; + +// TODO talk about how things will eventually be migrated to "-next" + +const About = () => { + return ( +
+
+ {/* Logo section */} +
+ Darklang Classic +
+ + {/* Main content - First Section */} +
+
+ Dark + + {" "} + is a new way of building serverless backends. Just code your + backend, with no infra, framework or deployment nightmares. + Build{" "} + + APIs + , + CRUD + apps, + internal tools + and + bots + - whatever your backend needs. +
+ +

+ The Classic version of Darklang is still accessible but is currently + in maintenance mode, with no ongoing development. Darklang-next is + the next iteration of Dark, applicable to both the cloud runtime and + to local scripts and CLIs +

+
+ + {/* Code Editor Image Section */} +
+ Darklang Editor Interface +
+ + {/* Key Capabilities */} +
+
+ {/* Internal Tools & Bots */} +
+

+ Internal Tools + & + Bots +

+

+ Dark is ideal for quickly building slackbots and automating + internal tools. Receive webhooks live, call out to 3rd party + APIs, store data, and schedule jobs - while building no + infrastructure. +

+ + Read more about using dark with Slack + +
+ + {/* REST APIs & Webhooks */} +
+

+ REST APIs + & + Webhooks +

+

+ Set up an API endpoint quickly enough to use it as a proof of + concept during a call. Immediately see the data from a webhook + to your endpoint. Call an external API using the HttpClient + library and see responses within the editor, or use workers to + do them in the background. Use the built-in package manager to + make external API calls really easily, and contribute your own + API integrations. +

+
+ + {/* CRUD apps */} +
+

+ CRUD + apps +

+

+ Get a working CRUD application in less than ten minutes by + setting up a few API endpoints and a datastore. Build out the + backend for a web or mobile app, whether a simple HTML form or + an entire product. +

+
+
+
+ + {/* Any Backend Section */} +
+

+ Any + Backend + That Requires... +

+ +
+ {/* Feature Card 1 */} +
+

+ API + Endpoints +

+
+ + {/* Feature Card 2 */} +
+

+ Data + Stores +

+
+ + {/* Feature Card 3 */} +
+

+ Background + Workers +

+
+ + {/* Feature Card 4 */} +
+

+ Scheduled + Jobs +

+
+
+ +

+ Dark lets you build any backend that needs API endpoints, data + stores, background workers, scheduled jobs, and calling HTTP APIs. + You just write the code in Dark, and we'll manage the rest. +

+ + + + {/* Access Darklang-classic CTA */} +
+

+ Access Darklang-classic +

+ +
+
+
+
+ ); +}; + +export default About; diff --git a/src/pages/Cloud/index.tsx b/src/pages/Cloud/index.tsx new file mode 100644 index 0000000..20ad743 --- /dev/null +++ b/src/pages/Cloud/index.tsx @@ -0,0 +1,22 @@ + + + +import React from "react"; + +const Cloud: React.FC = () => { + return ( +
+

the big host

+
    +
  • hosting of your code (git)
  • +
  • hosting of your deployed apps (CLI, backends, etc)
  • +
  • in-browser CLI access
  • +
  • in-browser editor
  • +
  • hosted MCP servers, LSP servers
  • +
  • CDN help
  • +
+
+ ); +}; + +export default Cloud; diff --git a/src/pages/Company/Sustainability.tsx b/src/pages/Company/Sustainability.tsx new file mode 100644 index 0000000..85e4bfc --- /dev/null +++ b/src/pages/Company/Sustainability.tsx @@ -0,0 +1,13 @@ +
+    Licensing
+    Cloud hosting
+    plz give us money
+
+    burndown chart?
+
+    {
+                  //   text: "Sponsor us",
+                  //   href: "https://github.com/sponsors/darklang",
+                  //   target: "_blank",
+                  // },
+
\ No newline at end of file diff --git a/src/pages/Company/index.tsx b/src/pages/Company/index.tsx new file mode 100644 index 0000000..2dc24f8 --- /dev/null +++ b/src/pages/Company/index.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +const Company: React.FC = () => { + return ( +
+Darklang has been around in various form since xxxxxx.
+
+## Vision
+
+## Mission
+
+## Funding, Sustainability, Licensing, and Business Model
+
+In order to work on our mission, towards our vision, we must be sustainable.
+
+[sponsor, licensing]
+
+(if you're interested in giving us $, ...)
+
+## Branding
+
+(link to another page)
+
+## Roadmap
+
+- [...]
+
+
+## Are we hiring?
+
+No, sorry, not currently. We're limited on funding.
+
+
+## History
+...
+
+    Licensing
+    Cloud hosting
+    plz give us money
+
+    burndown chart?
+
+ ); +}; + +export default Company; diff --git a/src/pages/Distribution/index.tsx b/src/pages/Distribution/index.tsx new file mode 100644 index 0000000..3e553c0 --- /dev/null +++ b/src/pages/Distribution/index.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +const Distribution: React.FC = () => { + return ( +
+
+        package management
+        source control
+        building artifacts for end users
+      
+

+ TODO: move this somewhere else +
+ Darklang is a cloud-native programming language and platform designed to simplify the development of serverless backends by introducing a "deployless" model. This approach aims to remove the complexities of traditional software deployment, allowing developers to focus on writing code rather than managing infrastructure, builds, or deployment pipelines. + + In traditional software development, deploying code involves multiple steps: writing code, committing it to a repository (e.g., via Git), creating pull requests, building assets, pushing containers to registries, and orchestrating deployments (e.g., via Kubernetes). Darklang eliminates roughly 60% of these steps by integrating the language, editor, and infrastructure into a cohesive platform. The result is a deployment process that takes approximately 50 milliseconds, enabling rapid iteration and testing in production. + + + The deployless model is analogous to serverless computing: just as serverless abstracts away server management, deployless abstracts away deployment management so that you don’t have to think about it + + Developers don’t need to configure build systems, containers, Kubernetes, or CI/CD pipelines. The platform handles scaling, monitoring, and optimization + + Feature flags allow developers to test code in production without exposing it to users, and precise access controls enhance security + + No Infrastructure Management: Developers avoid configuring servers, databases, or networking components. + + Developers spend less time on DevOps tasks, focusing on application logic +

+
+ ); +}; + +export default Distribution; \ No newline at end of file diff --git a/src/pages/Editing/index.tsx b/src/pages/Editing/index.tsx new file mode 100644 index 0000000..48ba738 --- /dev/null +++ b/src/pages/Editing/index.tsx @@ -0,0 +1,204 @@ +import React from "react"; + +import doubleGridSquare from "~/assets/double-grid-square.png"; +import darklangLogoFramed from "~/assets/darklang-logo-framed.png"; + +import Button from "../../common/ui/Button"; +import CodeEditor from "../../common/ui/CodeEditor"; +import CTASection from "../../common/ui/CTASection"; + +const Editing: React.FC = () => { + return ( +
+
+
+ Grid Pattern +
+ +
+
+
+
+ Darklang Logo +
+
+ +
+

Multi-Editor Support

+

+ Darklang's language server is designed to work across multiple + editing environments, providing a consistent experience + regardless of your preferred editor. +

+
+ + +
+
+
+
+
+ + {/* LSP Server Section */} +
+
Darklang LSP Server
+ +

+ Our language server is fully written in Darklang and follows the + Language Server Protocol (LSP), providing features like + autocompletion, real-time error checking, and hover documentation. It + is currently integrated with a lightweight VS Code extension, and we + plan to support more editors like Vim, Rider, and Sublime in the + future. +

+
+ + {/* Basic Features Section */} +
+
Basic Features
+ +
+ {/* Code Completion */} +
+

+ Code completion +

+ +
+ + {/* Syntax Highlighting */} +
+

+ Syntax highlighting +

+ +
+ + {/* Diagnostics */} +
+

+ Diagnostics +

+ +
+
+ +
+ {/* Hover */} +
+

+ Hover +

+ +
+ + {/* Go to Definition */} +
+

+ Go to definition +

+ +
+
+
+ + {/* Customizing & Creating Language Servers Section */} +
+
+ Customizing & Creating Language Servers +
+ +
+

+ Many of our language tools are fully accessible to users. Just like + forking and editing your own code, you can fork the language server + to change how features like onHover, autocompletion, or diagnostics + work. +

+ +

+ It's also easy to create your own language servers, whether for + testing new ideas or developing specialized tools +

+
+
+ + {/* Extension Section */} +
+
Extension
+ +
+

+ We are currently focused on building a VS Code extension because of + its rich API ecosystem and powerful FileSystemProvider (FSP) + capabilities. Unlike traditional development where code exists as + plain text files on disk, Darklang's code is stored in a package + manager, making VS Code's FSP particularly valuable for our + implementation. +

+ +

+ While VS Code is our starting point, we're actively planning support + for additional editors including Vim, Sublime Text, and Rider. +

+
+
+ + {/* Getting Started Section */} + +
+

Getting Started

+

+ Try the VS Code extension or use it instantly on{" "} + + editor.darklang.com + + ! +

+
+ +
+
+
+
+ ); +}; + +export default Editing; diff --git a/src/pages/Execution/index.tsx b/src/pages/Execution/index.tsx new file mode 100644 index 0000000..4496557 --- /dev/null +++ b/src/pages/Execution/index.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +const Execution: React.FC = () => { + return ( +
+    interpeted
+
+    TODO: compiler stuff
+    runtime typechecking [link to TC page]
+
+    rough metrics of perf.
+
+    link to github issues
+
+ ); +}; + +export default Execution; diff --git a/src/pages/For/index.tsx b/src/pages/For/index.tsx new file mode 100644 index 0000000..01c80cd --- /dev/null +++ b/src/pages/For/index.tsx @@ -0,0 +1,39 @@ +import React from "react"; + +const For: React.FC = () => { + return ( +
+I'm thinking to have a bunch of pages like
+darklang.com/for/web-developers
+with dedicated content for groups of folks who we think might appreciate Darklang.
+
+here are some ideas
+
+darklang.com/for/fsharp-developers
+darklang.com/for/home-automation
+darklang.com/for/eInk-devices
+darklang.com/for/web-developers
+darklang.com/for/people-with-money (letter asking them to invest etc?)
+darklang.com/for/people-who-want-money (entrepreneurs? scripters? people with servers?)
+darklang.com/for/security-nerds
+darklang.com/for/unix-users
+darklang.com/for/accessibility
+darklang.com/for/AI-developers
+darklang.com/for/lazy-people
+darklang.com/for/folks-who-collect-domains
+darklang.com/for/python-developers
+darklang.com/for/web-scrapers (the web is ridden with flies, you can hardly see through. scrape the web and provide) also good for folks who are into those browser extensions... something monkey? that remove ads and such
+darklang.com/for/privacy
+darklang.com/for/local-first
+darklang.com/for/small-businesses (SSG; wordpress alt.; affordable software solutions and contracting)
+
+
+
+
+in each of these, include expandable section for context for those outside the know
+
+
+ ); +}; + +export default For; diff --git a/src/pages/GettingStarted/index.tsx b/src/pages/GettingStarted/index.tsx new file mode 100644 index 0000000..da2b88b --- /dev/null +++ b/src/pages/GettingStarted/index.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +const GettingStarted: React.FC = () => { + return ( +
+    Not sure if we should point to devcontainer yet
+    , or just say "wait a bit"
+    , or something else.
+
+ ); +}; + +export default GettingStarted; diff --git a/src/pages/Home/AsyncRuntime.tsx b/src/pages/Home/AsyncRuntime.tsx new file mode 100644 index 0000000..09d254a --- /dev/null +++ b/src/pages/Home/AsyncRuntime.tsx @@ -0,0 +1,122 @@ +import React from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +interface FeatureCardProps { + title: React.ReactNode; + description: React.ReactNode; + className?: string; +} + +const FeatureCard: React.FC = ({ + title, + description, + className = "", +}) => ( +
+
+
+
+
+
+

{title}

+
+
{description}
+
+); + +const AsyncRuntime = () => { + return ( +
+
+ + Async Runtime + + +
+ {/* Left side */} +
+ + No async / await + + } + description={ +

+ Adding async and await keywords to every language was a + mistake. It exposes the complexity of concurrency and + multi-threading to languages which were originally designed + for simplicity. +

+ } + /> +
+ + {/* Right column card */} +
+ + Concurrent and{" "} + parallel execution + via data-dependencies + + } + description={ +
+

+ When you make an async request, it first waits for any + arguments that are async, and starts when they're done. If + another function call needs to use the result, it will wait + for it before starting. +

+

+ Since darklang values are immutable, there won't be any race + conditions from this. +

+
+ } + /> +
+ + {/* Second row cards */} +
+ + Fully asynchronous{" "} + runtime + + } + description={ +

+ Darklang has a fully asynchronous runtime, so making a Http + call or reading a file doesn't block the runtime. +

+ } + /> + + + Powerful{" "} + escape hatches + + } + description={ +

+ We provide powerful escape hatches if you need async ordering + that doesn't match the data dependencies of your program. +

+ } + /> +
+
+
+
+ ); +}; + +export default AsyncRuntime; diff --git a/src/pages/Home/BackendFeatures.tsx b/src/pages/Home/BackendFeatures.tsx new file mode 100644 index 0000000..1f23f2a --- /dev/null +++ b/src/pages/Home/BackendFeatures.tsx @@ -0,0 +1,367 @@ +import React, { useState, useRef, useEffect } from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; +import CodeDisplay from "../../common/ui/CodeDisplay"; + +interface FeatureButtonProps { + icon: React.ReactNode; + isMonoFont?: boolean; + label: string; + isActive: boolean; + hasDropdown?: boolean; + onClick: () => void; + subOptions?: { label: string; value: string }[]; + onSubOptionClick?: (value: string) => void; +} + +const FeatureButton: React.FC = ({ + icon, + isMonoFont = false, + label, + isActive, + hasDropdown = false, + onClick, + subOptions = [], + onSubOptionClick, +}) => { + const [showDropdown, setShowDropdown] = useState(false); + const dropdownRef = useRef(null); + + const handleClick = () => { + if (hasDropdown) { + setShowDropdown(!showDropdown); + } else { + onClick(); + } + }; + + // Handle clicking outside of dropdown + useEffect(() => { + const handleOutsideClick = (event: MouseEvent) => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(event.target as Node) + ) { + setShowDropdown(false); + } + }; + + if (showDropdown) { + document.addEventListener("mousedown", handleOutsideClick); + } + + return () => { + document.removeEventListener("mousedown", handleOutsideClick); + }; + }, [showDropdown]); + + return ( +
+
+ + {icon} + + {label} + {hasDropdown && } +
+ + {showDropdown && hasDropdown && ( +
+ {subOptions.map(option => ( +
{ + if (onSubOptionClick) { + onSubOptionClick(option.value); + setShowDropdown(false); + } + }} + > + {option.label} +
+ ))} +
+ )} +
+ ); +}; + +// Code examples for each feature +const codeExamples = { + httpHandlerGET: `[] +let _handler _req = + let products = Stdlib.DB.getAll ProductsDB + + let body = + products + |> Builtin.jsonSerialize + |> Stdlib.String.toBytes + + Stdlib.Http.responseWithHeaders + body + 200L + [("Content-Type", "application/json")]`, + + httpHandlerPOST: `[] +let _handler req = + // Parse the request body + let body = + req.body + |> Stdlib.String.fromBytes + |> Builtin.jsonDeserialize<{ + name: String + price: Float + description: String + category: String + }> + + // Create a new product + let newProduct = { + id = Stdlib.Uuid.generate() + name = body.name + price = body.price + description = body.description + category = body.category + createdAt = Stdlib.Date.now() + indexed = false + } + + // Save to database using the UUID as key + Stdlib.DB.set newProduct newProduct.id ProductsDB + + // Emit product to background worker + emit { productId = newProduct.id } "product-indexer" + + // Return the created product + let responseBody = + newProduct + |> Builtin.jsonSerialize + |> Stdlib.String.toBytes + + Stdlib.Http.responseWithHeaders + responseBody + 201L + [("Content-Type", "application/json")]`, + + httpHandlerDELETE: `[] +let _handler req = + let productId = req.pathParams["id"] |> Stdlib.Uuid.parse |> Builtin.unwrap + + match Stdlib.DB.get productId ProductsDB with + | Some product -> + Stdlib.DB.delete productId ProductsDB + + Builtin.printline $"Product {productId} deleted" + + Stdlib.Http.response + (Stdlib.String.toBytes "") + 204L + + | None -> + // Product not found + Stdlib.Http.responseWithHeaders + Stdlib.String.toBytes "Product not found" + 404L + [("Content-Type", "application/json")]`, + + dataStores: `// Define our product type +type Product = { + id: Stdlib.Uuid.UUID + name: String + price: Float + description: String + category: String + createdAt: Date + indexed: Bool +} + +// Create the database +[] +type ProductsDB = Product`, + + scheduledJobs: `[] +let _handler () = + // Count total products + let products = Stdlib.DB.getAll ProductsDB + let totalProducts = Stdlib.List.length products + + // Send email report + Stdlib.Email.send { + to = "admin@example.com" + subject = "Daily Product Report" + body = $"Total Products: {totalProducts}" + } + + Builtin.log "Daily report sent successfully"`, + + backgroundWorkers: `// Define a worker to process products asynchronously +[] +let _handler = + // Access the event data (comes from emit) + let productId = event.productId + + // Get the product from database + match Stdlib.DB.get productId ProductsDB with + | Some product -> + // Log start of processing + Builtin.log $"Processing product {product.id}: {product.name}" + + // Update the product status + let updatedProduct = { product with indexed = true } + Stdlib.DB.set updatedProduct product.id ProductsDB + + // Log completion + Builtin.log $"Product {product.id} marked as indexed" + + | None -> + Builtin.log $"Product {productId} not found" +`, +}; + +const BackendFeatures: React.FC = () => { + const [selectedFeature, setSelectedFeature] = + useState("httpHandlerGET"); + + // HTTP handler dropdown options + const httpHandlerOptions = [ + { label: "GET /products", value: "httpHandlerGET" }, + { label: "POST /products", value: "httpHandlerPOST" }, + { label: "DELETE /products/:id", value: "httpHandlerDELETE" }, + ]; + + // Get the code for the currently selected feature + const currentCode = codeExamples[selectedFeature]; + + return ( +
+
+
+ + Build a complete backend with Darklang + + +

+ Darklang lets you easily develop backend applications, seamlessly deployable to the cloud. + You can build tiny applications to connect two services, or large scale applications with tens of thousands of users. + Code is written in + collaboration with AI and is instantly and safely deployed on our + hosted platform or yours, so you can focus on writing code while we + handle the rest +

+ +

+ You can build any backend that needs: +

+
+ +
+
+ setSelectedFeature("httpHandlerGET")} + subOptions={httpHandlerOptions} + onSubOptionClick={value => + setSelectedFeature(value as keyof typeof codeExamples) + } + /> + + + + + + + } + label="Data stores" + isActive={selectedFeature === "dataStores"} + onClick={() => setSelectedFeature("dataStores")} + /> + + setSelectedFeature("scheduledJobs")} + /> + + + + + } + label="Background workers" + isActive={selectedFeature === "backgroundWorkers"} + onClick={() => setSelectedFeature("backgroundWorkers")} + /> +
+ +
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+ ); +}; + +export default BackendFeatures; diff --git a/src/pages/Home/BlogPosts.tsx b/src/pages/Home/BlogPosts.tsx new file mode 100644 index 0000000..bef480b --- /dev/null +++ b/src/pages/Home/BlogPosts.tsx @@ -0,0 +1,51 @@ +import React from "react"; + +import { BlogPostCard } from "../../common/ui/BlogPostCard"; +import SectionTitle from "../../common/ui/SectionTitle"; + +interface BlogPost { + id: string; + author: string; + date: string; + title: string; + excerpt: string; + imageUrl: string; + slug: string; +} + +interface BlogPostsProps { + posts: BlogPost[]; +} + +export const BlogPosts: React.FC = ({ posts }) => { + return ( +
+
+ + Recent Blog Posts + + +
+ {posts.map(post => ( + + ))} +
+
+
+ ); +}; + +export default BlogPosts; diff --git a/src/pages/Home/BlogPostsExample.tsx b/src/pages/Home/BlogPostsExample.tsx new file mode 100644 index 0000000..b4ae9f8 --- /dev/null +++ b/src/pages/Home/BlogPostsExample.tsx @@ -0,0 +1,43 @@ +import React from "react"; + +import BlogPosts from "./BlogPosts"; + +// Mock data for blog posts +const mockPosts = [ + { + id: "1", + author: "Stachu Korick", + date: "12 Mar 2024", + title: "An overdue status update on Darklang", + excerpt: + "An overdue status update on Darklang. We've been working hard at Darklang for the past year, but haven't been very vocal about what we've been up to...", + imageUrl: "src/assets/The_Sower-1.jpg", + slug: "https://blog.darklang.com/an-overdue-status-update/", + }, + { + id: "2", + author: "Paul Biggar", + date: "28 Mar 2023", + title: "Darklang is going all-in on AI", + excerpt: + "Like an aging rock star making a final stab at glory, I'm delighted to announce that Darklang is going all in on AI/GPT. As everyone knows, the folks over at...", + imageUrl: "src/assets/murmuration.webp", + slug: "https://blog.darklang.com/gpt/", + }, + { + id: "3", + author: "Paul Biggar", + date: "24 Feb 2023", + title: "Sponsoring Darklang", + excerpt: + "We'd love you to sponsor Darklang's development! Long term, we'd like Darklang to be sustainable from the community. In the future, we expect paid accounts will support our development...", + imageUrl: "src/assets/John_Constable_-_The_Hay_Wain_-1821-.jpg", + slug: "https://blog.darklang.com/sponsor-darklang/", + }, +]; + +export const BlogPostsExample: React.FC = () => { + return ; +}; + +export default BlogPostsExample; diff --git a/src/pages/Home/CLI.tsx b/src/pages/Home/CLI.tsx new file mode 100644 index 0000000..9ba1357 --- /dev/null +++ b/src/pages/Home/CLI.tsx @@ -0,0 +1,448 @@ +import React, { useState } from "react"; + +import cliImage from "~/assets/cli.png"; + +import SectionTitle from "../../common/ui/SectionTitle"; +import CodeDisplay from "../../common/ui/CodeDisplay"; + +const CLI: React.FC = () => { + const [selectedScript, setSelectedScript] = useState("typescript"); + + const scriptOptions = [ + { id: "typescript", label: "Simple Script" }, + { id: "bash", label: "Backup script" }, + { id: "deployment", label: "Deployment Script" }, + ]; + + // Bash code for TypeScript CommonJS files search (Simple Script) + const bashTypeScriptCode = `find_large_typescript_commonjs_files() { + local search_path="$1" + + find "$search_path" -type f | while read -r file_path; do + + if [[ "$file_path" != *.ts && "$file_path" != *.mjs && + "$file_path" != *.cjs ]]; then + echo "Skipping - wrong file type:$file_path" + continue + fi + + line_count=$(wc -l < "$file_path") + if [ "$line_count" -le 600 ]; then + echo "Skipping - too short: $file_path" + continue + fi + + if grep -q -E "const .* = require\\(.*\\)" "$file_path"; then + echo "Found one: $file_path" + fi + done +} + +find_large_typescript_commonjs_files "./"`; + + // Darklang code for TypeScript CommonJS files search (Simple Script) + const darklangTypeScriptCode = `let findLargeTypescriptCommonJSFiles (path : String) = + Directory.traverse (fun path → + if not (List.oneOf (File.extension path) [".ts", ".mjs", ".cjs"]) then + print $"Skipping - wrong file type: {path}" + else + let contents = File.readString path + let lines = String.splitNewlines contents + if (List.length lines) < 600 then + print $"Skipping - too short: {path}" + else + let isCommonjs = + lines |> List.any (fun line → + line |> Regex.matches "/const .* = require\\(.*\\)/" + ) + if isCommonjs then + print $"Found one: {path}" + ) + +findLargeTypescriptCommonJSFiles "./"`; + + // Backup bash script example + const bashSimpleCode = `#!/bin/bash + +# Simple script to backup a directory +BACKUP_DIR="/home/user/documents" +TARGET_DIR="/backup/$(date +%Y-%m-%d)" + +# Create target directory if it doesn't exist +mkdir -p "$TARGET_DIR" + +# Copy files with progress indicator +echo "Backing up $BACKUP_DIR to $TARGET_DIR..." +rsync -av --progress "$BACKUP_DIR/" "$TARGET_DIR/" + +# Check if backup was successful +if [ $? -eq 0 ]; then + echo "Backup completed successfully!" +else + echo "Backup failed with error code $?" + exit 1 +fi + +# Cleanup old backups (keep last 7 days) +find /backup -type d -mtime +7 -exec rm -rf {} \\; 2>/dev/null + +echo "Backup process completed."`; + + // Darklang backup script example + const darklangSimpleCode = `// Simple script to backup a directory +let backupDirectory (sourcePath : String, keepDays : Int) = + // Create timestamp for backup folder + let timestamp = Date.now() |> Date.format "yyyy-MM-dd" + let targetDir = $"/backup/{timestamp}" + + // Create directory and attempt backup + FileSystem.createDirectory targetDir + |> Result.andThen (fun _ -> + FileSystem.copyDirectory sourcePath targetDir + |> Result.map (fun _ -> + Builtin.printline $"Backup completed successfully to {targetDir}" + + // Find and remove old backups + FileSystem.listDirectories "/backup" + |> List.filter (fun dir -> + let dirDate = Path.basename dir |> Date.parse + Date.diffDays dirDate (Date.now()) > keepDays) + |> List.forEach FileSystem.deleteDirectory + ) + ) + |> Result.mapError (fun e -> + Builtin.printline $"Backup failed: {e}" + ) + |> ignore + +// Execute backup with 7 day retention +backupDirectory "/home/user/documents" 7`; + + // Deployment script example + const bashDeploymentCode = `#!/bin/bash + +# Deployment script for web application + +APP_NAME="mywebapp" +DEPLOY_ENV=$1 +SOURCE_DIR="./dist" +SERVER_USER="deploy" + +# Validate environment argument +if [[ "$DEPLOY_ENV" != "staging" && "$DEPLOY_ENV" != "production" ]]; then + echo "Error: Please specify either 'staging' or 'production' as environment" + echo "Usage: $0 " + exit 1 +fi + +# Set server based on environment +if [[ "$DEPLOY_ENV" == "production" ]]; then + SERVER="production.example.com" + TARGET_DIR="/var/www/production/$APP_NAME" +else + SERVER="staging.example.com" + TARGET_DIR="/var/www/staging/$APP_NAME" +fi + +echo "Deploying $APP_NAME to $DEPLOY_ENV environment..." + +# Build the application +echo "Building application..." +npm run build + +# Check if build was successful +if [ $? -ne 0 ]; then + echo "Build failed! Aborting deployment." + exit 1 +fi + +# Create backup of current deployment if it exists +ssh $SERVER_USER@$SERVER "if [ -d $TARGET_DIR ]; then cp -r $TARGET_DIR _backup_$(date +%Y%m%d%H%M%S); fi" + +# Deploy application to server +echo "Uploading to $SERVER..." +rsync -avz --delete $SOURCE_DIR/ $SERVER_USER@$SERVER:$TARGET_DIR/ + +# Run post-deployment tasks +echo "Running post-deployment tasks..." +ssh $SERVER_USER@$SERVER "cd $TARGET_DIR && ./post-deploy.sh $DEPLOY_ENV" + +echo "Deployment to $DEPLOY_ENV completed successfully!"`; + + // Darklang deployment script example + const darklangDeploymentCode = `// Deployment script for web application +type Env = Production | Staging + +let deployApplication (env : Env, appName : String) = + // Set server and paths based on environment + let (server, targetDir) = + match env with + | Production -> ("production.example.com", $"/var/www/production/{appName}") + | Staging -> ("staging.example.com", $"/var/www/staging/{appName}") + + Builtin.printline $"Deploying {appName} to {env} environment..." + + // Build the application + Builtin.printline "Building application..." + Process.run "npm" ["run", "build"] + |> Result.andThen (fun _ -> + // Backup existing deployment + let backupCmd = $" + if [ -d {targetDir} ]; then + cp -r {targetDir} {targetDir}_backup_$(date +%Y%m%d%H%M%S) + fi" + + Server.execute server backupCmd + |> Result.andThen (fun _ -> + // Deploy files to server + Builtin.printline $"Uploading to {server}..." + RemoteFS.sync { + sourcePath = "./dist" + targetServer = server + targetPath = targetDir + deleteExtraFiles = true + } + |> Result.andThen (fun _ -> + // Run post-deployment tasks + Builtin.printline "Running post-deployment tasks..." + Server.execute server $"cd {targetDir} && ./post-deploy.sh {env}" + |> Result.map (fun _ -> + Builtin.printline $"Deployment to {env} completed successfully!" )))) + |> Result.mapError (fun e -> + Builtin.printline $"Deployment failed: {e}") + +// Execute deployment +deployApplication Staging "mywebapp"`; + + // Get the appropriate code based on selected script + const getCode = (scriptId: string) => { + switch (scriptId) { + case "typescript": + return { bash: bashTypeScriptCode, darklang: darklangTypeScriptCode }; + case "bash": + return { bash: bashSimpleCode, darklang: darklangSimpleCode }; + case "deployment": + return { bash: bashDeploymentCode, darklang: darklangDeploymentCode }; + default: + return { bash: bashTypeScriptCode, darklang: darklangTypeScriptCode }; + } + }; + + const currentCode = getCode(selectedScript); + + return ( +
+
+ + {" "} + A CLI Runtime to Replace your Bash

and Python Scripts +
+ +
+ {/* Left side - Text content */} +
+
+
+ + + +
+

+ Darklang's CLI is a better alternative to Bash, combining its + power with the simplicity and safety of modern programming + languages. Enabling you to write scripts without confusing + errors or dependency issues. +

+
+ +
+
+ {/* Feature 1 */} +
+
+ + + + +
+
+

+ Type-safe by design +

+

+ Using static types to help ensure correctness +

+
+
+ + {/* Feature 2 */} +
+
+ + + +
+
+

+ Built-in Packages +

+

+ No Npm install, no dependency headaches +

+
+
+ + {/* Feature 3 */} +
+
+ + + +
+
+

+ Cross-platform +

+

+ Running on macOS, Linux, and Windows +

+
+
+
+
+ + + Discover Darklang CLI features and how it solves scripting + problems → + +
+ + {/* Right side */} +
+
+ Darklang CLI interface +
+
+
+ +
+

+ Darklang compared to Bash and Python +

+
+ {/* Sidebar navigation */} +
+
    + {scriptOptions.map(option => ( +
  • setSelectedScript(option.id)} + > + {option.label} +
  • + ))} +
+
+ + {/* Code comparison section */} +
+ {/* Left side: Bash */} +
+
+
+
+
+
+
+
+ +
+
+
-Bash-
+
+ + {/* Right side: Darklang */} +
+
+
+
+
+
+
+
+ +
+
+
-Darklang-
+
+
+
+
+
+
+ ); +}; + +export default CLI; diff --git a/src/pages/Home/DeploylessCloud.tsx b/src/pages/Home/DeploylessCloud.tsx new file mode 100644 index 0000000..8b5f4ea --- /dev/null +++ b/src/pages/Home/DeploylessCloud.tsx @@ -0,0 +1,148 @@ +import React, { useState } from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +type FeatureCardProps = { + icon: React.ReactNode; + title: string; + description: string; +}; + +const FeatureCard: React.FC = ({ + icon, + title, + description, +}) => { + return ( +
+
{icon}
+
+

{title}

+

{description}

+
+
+ ); +}; + +const LightningIcon = ({ color = "text-purple-lbg" }: { color?: string }) => ( + + + +); + +const DeploylessCloud: React.FC = () => { + const [activeTab, setActiveTab] = useState<"deployless" | "nosetup">( + "deployless", + ); + + return ( +
+
+ + Deployless, Infraless Cloud Apps + + +
+
+ +
+ +
+ +
+
+ +
+ {activeTab === "deployless" && ( +
+ } + title="Write code and it's immediately available" + description="No build step, no wait time, no deployment pipeline your code is live as soon as you type." + /> + + } + title="Feature flags for controlled rollouts" + description="Control exactly when and for whom new features go live. Test in production safely with instant rollback capability" + /> + + } + title="Development/Production Parity" + description="Your development environment matches the production environment, so you can test with confidence." + /> + + } + title="Integrated code review and testing" + description="Review code, run tests, and collaborate seamlessly in one place" + /> +
+ )} + + {activeTab === "nosetup" && ( +
+ } + title="Instant infrastructure creation" + description="Language-native HTTP handlers, Databases, CRONs and queues, without thinking about servers, containers, or deployment" + /> + + } + title="Simplified Architecture" + description="No need to worry about connection poolers, sharding, indexes, load balancers, cloud services, or system administration—everything runs seamlessly in the background" + /> +
+ )} +
+
+
+ ); +}; + +export default DeploylessCloud; diff --git a/src/pages/Home/DesignedForGenAI.tsx b/src/pages/Home/DesignedForGenAI.tsx new file mode 100644 index 0000000..430cd38 --- /dev/null +++ b/src/pages/Home/DesignedForGenAI.tsx @@ -0,0 +1,142 @@ +import React from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +const DesignedForGenAI: React.FC = () => { + return ( +
+
+ + Designed for GenAI + + +
+ {/* First Card */} +
+
+ Works with GitHub Copilot{" "} + for AI-powered code suggestions +
+
    +
  • + - + Get real-time code suggestions while writing Dark applications +
  • +
  • + - + Accelerate development with context-aware suggestions +
  • +
+
+ + {/* Second Card */} +
+
+ Build short CLI programs{" "} + from prompts +
+
+ dark prompt "find all js files which don't have a CSS file of the + same name" +
+
+ + {/* Third Card */} +
+ +
+ Use any LLM +
+
    +
  • + - + darklang's fine-tuned models +
  • +
  • + - + local OSS models +
  • +
  • + - + commercial models via API +
  • +
+
+ + {/* Fourth Card */} +
+ +
+ Build vendor SDKs from + prompts and OpenAPI docs +
+
    +
  • + - + Transform technical API documentation into usable code libraries +
  • +
  • + - + Turn technical documentation into developer-friendly toolkits +
  • +
  • + - + Update SDKs automatically when APIs change +
  • +
+
+ + {/* Fifth Card */} +
+ +
+ Build complex programs{" "} + with darklang AI agents +
+
+ + Create next-level applications by leveraging darklang's AI + agents to handle complex workflows. These agents can analyze + requirements, suggest implementation strategies, generate code, + and help troubleshoot issues—all while maintaining code quality + and adhering to best practices. + +
+
+ + {/* MCP Card */} +
+ +
+ + Create MCP servers + +
+ +
    +
  • + - + + Allow AI models to access external tools/resources, execute + code, and interact with various services + +
  • +
  • + - + Create custom MCP servers for your systems +
  • +
+
+
+
+
+ ); +}; + +export default DesignedForGenAI; diff --git a/src/pages/Home/DevelopmentSteps.tsx b/src/pages/Home/DevelopmentSteps.tsx new file mode 100644 index 0000000..78c6b68 --- /dev/null +++ b/src/pages/Home/DevelopmentSteps.tsx @@ -0,0 +1,676 @@ +import { useState, useEffect } from "react"; + +const DevelopmentSteps = () => { + // Animation state for the node side + const [activeNodeStep, setActiveNodeStep] = useState(0); + const [activeSubSteps, setActiveSubSteps] = useState<{ + [key: string]: number; + }>({ + setup: 1, // Start with 2 substeps completed in Setup + }); + const [completedNodeSteps, setCompletedNodeSteps] = useState([]); + + // Animation state for the dark side + const [darkCompletedSteps, setDarkCompletedSteps] = useState(0); // Start with none completed + const [activeTab, setActiveTab] = useState("script"); // Start with cloud tab active + + // The complete list of node.js steps with their substeps + const nodeSteps = [ + { + id: "setup", + title: "Setup", + substeps: [ + { id: "install-nodejs", title: "Install Node.js and NPM" }, + { id: "create-project", title: "Create a new Node.js project" }, + { id: "npm-init", title: "Initialize project with npm init" }, + ], + }, + { + id: "development", + title: "Development", + substeps: [ + { id: "write-code", title: "Write application code" }, + { id: "env-vars", title: "Set up environment variables" }, + { id: "dependencies", title: "Install required dependencies" }, + { id: "env-vars2", title: "Set up environment variables" }, + { + id: "config-files", + title: "Create configuration files (.gitignore, package.json, etc)", + }, + ], + }, + { + id: "database", + title: "Database Setup", + substeps: [ + { id: "choose-db", title: "Choose a database system" }, + { id: "setup-db", title: "Set up database" }, + { id: "create-schema", title: "Create database schema" }, + { id: "config-connection", title: "Configure database connection" }, + { id: "setup-orm", title: "Set up ORM" }, + ], + }, + { + id: "version-control", + title: "Version Control", + substeps: [ + { id: "init-git", title: "Initialize Git repository" }, + { id: "commit-push", title: "Create branch, commit, and push code" }, + ], + }, + { + id: "testing", + title: "Testing", + substeps: [ + { id: "unit-tests", title: "Write unit tests" }, + { id: "integration-tests", title: "Write integration tests" }, + { id: "test-env", title: "Set up test environment" }, + { id: "run-tests", title: "Run tests locally" }, + ], + }, + { + id: "infrastructure", + title: "Infrastructure", + substeps: [ + { id: "choose-hosting", title: "Choose a hosting provider" }, + { + id: "create-account", + title: "Create an account with the hosting provider", + }, + { id: "register-domain", title: "Register a domain name (optional)" }, + { id: "prod-db", title: "Set up production database" }, + ], + }, + { + id: "deployment", + title: "Deployment", + substeps: [ + { id: "build-process", title: "Configure Build process" }, + { + id: "env-hosting", + title: "Setup environment variables on hosting platform", + }, + { id: "deploy-app", title: "Deploy application to hosting" }, + { id: "setup-cicd", title: "Set up CI/CD" }, + { id: "test-deployed", title: "Test deployed application" }, + { id: "launch", title: "Launch application to users" }, + ], + }, + ]; + + // Dark app CLI script steps + const darkScriptSteps = [ + { + id: "get-cli", + title: "Get CLI", + description: "from https://github.com/darklang/dark/releases", + }, + { + id: "open-cli", + title: "Open CLI", + optional: true, + description: "Install is optional", + }, + { + id: "write-code", + title: "Write code", + }, + { + id: "debug-code", + title: "Debug code", + notice: "nothing to setup", + description: "using traces", + }, + { + id: "run-code", + title: "Run code", + description: + "As soon as functions/types/constants are created they are accessible publicly (or privately) in the package manager", + }, + { + id: "share-code", + title: "Share code", + optional: true, + description: + "Run $ darklang share @user/myModule.myFnName to instantly generate a shareable link for your code", + }, + { + id: "deploy-code", + title: "Deploy code", + optional: true, + description: + "Run $ darklang deploy @user/myModule.myFnName to deploy your code to our cloud or yours", + }, + ]; + + // Dark app Cloud steps (based on your screenshot) + const darkCloudSteps = [ + { + id: "go-to-editor", + title: "Go to editor.darklang.com", + description: + "or download our extension from https://marketplace.visualstudio.com/items?itemName=Darklang.darklang-vs-code-extension", + }, + { + id: "write-code", + title: "Write code", + notice: "Ready to go—no setup needed", + description: + "create functions, types, DBs, HTTP handlers, Crons, Workers, etc.", + }, + { + id: "debug-code", + title: "Debug code", + notice: "no setup needed", + description: "using traces", + }, + { + id: "run-code", + title: "Run code", + description: + "As soon as functions/types/constants are created they are accessible publicly (or privately) in the package manager.", + }, + { + id: "share-code", + title: "Share code", + optional: true, + description: + "Click the share button to instantly generate a shareable link for your code.", + }, + { + id: "instant-deploy", + title: "Instant Deploy", + optional: true, + }, + ]; + + // Get the active dark steps based on the selected tab + const darkSteps = activeTab === "script" ? darkScriptSteps : darkCloudSteps; + + // Stats + const nodeStats = { + timeSpent: "12mins 34s", + dependencyIssues: "5 errors", + packagesInstalled: "67 packages", + }; + + const darkStats = { + timeSpent: "1mins 23s", + dependencyIssues: "0 errors", + packagesInstalled: "0 packages", + }; + + // Animation effect for node steps + useEffect(() => { + let animationTimer: ReturnType; + + const progressAnimation = () => { + // Get current step info + const currentStepIndex = activeNodeStep; + + if (currentStepIndex >= nodeSteps.length) { + // Animation has finished all steps + return; + } + + const currentStep = nodeSteps[currentStepIndex]; + const currentStepId = currentStep.id; + const substepCount = currentStep.substeps.length; + const currentSubStepIndex = activeSubSteps[currentStepId] ?? -1; + + if (currentSubStepIndex < substepCount - 1) { + // Move to next substep + setActiveSubSteps(prev => ({ + ...prev, + [currentStepId]: currentSubStepIndex + 1, + })); + } else { + // Current step is complete, add to completed steps + setCompletedNodeSteps(prev => [...prev, currentStepIndex]); + + // Move to next main step + const nextStepIndex = currentStepIndex + 1; + + if (nextStepIndex < nodeSteps.length) { + setTimeout(() => { + setActiveNodeStep(nextStepIndex); + + // Pre-initialize substeps for the next step + setActiveSubSteps(prev => ({ + ...prev, + [nodeSteps[nextStepIndex].id]: -1, + })); + }, 400); // Slight delay before moving to next step + } + } + }; + + // Start the animation and run it every 700ms - slower for Node.js side + animationTimer = setInterval(progressAnimation, 700); + + return () => { + if (animationTimer) { + clearInterval(animationTimer); + } + }; + }, [activeNodeStep, activeSubSteps, nodeSteps]); + + // Handle the final step completion (when the deployment step is done) + useEffect(() => { + // If the last step is in the completed steps, we should mark all as completed + if (completedNodeSteps.includes(nodeSteps.length - 1)) { + setActiveNodeStep(nodeSteps.length); // Move past the last step + } + }, [completedNodeSteps, nodeSteps.length]); + + // Animation effect for Dark steps + useEffect(() => { + if (darkCompletedSteps < darkSteps.length) { + const darkInterval = setInterval(() => { + setDarkCompletedSteps(prev => + prev < darkSteps.length ? prev + 1 : prev, + ); + }, 1200); // Keep this at the faster speed + + return () => clearInterval(darkInterval); + } + }, [darkCompletedSteps, darkSteps.length]); + + // Helper to determine if a step is complete + const isNodeStepComplete = (index: number) => { + return completedNodeSteps.includes(index) || index < activeNodeStep; + }; + + // Helper to determine if a step is active + const isNodeStepActive = (index: number) => { + return index === activeNodeStep && activeNodeStep < nodeSteps.length; + }; + + // Helper to determine if a substep is complete + const isSubStepComplete = (stepIndex: number, subStepIndex: number) => { + if (isNodeStepComplete(stepIndex)) return true; + + const stepId = nodeSteps[stepIndex].id; + const currentSubStep = activeSubSteps[stepId] || -1; + + return stepIndex === activeNodeStep && subStepIndex <= currentSubStep; + }; + + // Helper to determine if a Dark step is complete + const isDarkStepComplete = (index: number) => { + return index < darkCompletedSteps; + }; + + return ( +
+
+

+ Get started in no time +

+ +
+ {/* Node.js App */} +
+

Building a Node app

+ + {/* Stats */} +
+
+
+ + + +
+
+
+ Time Spent on Setup +
+
+ {nodeStats.timeSpent} +
+
+
+ +
+
+ + + +
+
+
+ Dependency Issues +
+
+ {nodeStats.dependencyIssues} +
+
+
+ +
+
+ + + +
+
+
+ Packages Installed +
+
+ {nodeStats.packagesInstalled} +
+
+
+
+ + {/* Steps */} +
+ {/* Vertical line */} +
+ + {/* All steps */} +
+ {nodeSteps.map((step, stepIndex) => ( +
+ {/* Main step with circle */} +
+
+ {(isNodeStepComplete(stepIndex) || + isNodeStepActive(stepIndex)) && ( + + + + )} +
+
+ {step.title} +
+
+ + {/* Show substeps only for the active step */} + {isNodeStepActive(stepIndex) && ( +
+ {step.substeps.map((substep, subIndex) => { + const isCompleted = isSubStepComplete( + stepIndex, + subIndex, + ); + const isInProgress = + stepIndex === activeNodeStep && + subIndex === (activeSubSteps[step.id] || -1) + 1; + + return ( +
+ {/* Substep line */} +
+ + {/* Substep with circle */} +
+
+ {/* This creates the partial fill effect */} + {isCompleted && ( +
+ )} +
+
+ {substep.title} +
+
+
+ ); + })} +
+ )} +
+ ))} +
+
+
+ + {/* Dark App */} +
+

Building a Dark app

+ + {/* Stats */} +
+
+
+ + + +
+
+
+ Time Spent on Setup +
+
+ {darkStats.timeSpent} +
+
+
+ +
+
+ + + +
+
+
+ Dependency Issues +
+
+ {darkStats.dependencyIssues} +
+
+
+ +
+
+ + + +
+
+
+ Packages Installed +
+
+ {darkStats.packagesInstalled} +
+
+
+
+ + {/* Tabs */} +
+
+ + +
+
+ + {/* Steps */} +
+ {/* Vertical line */} +
+ + {/* All steps */} +
+ {darkSteps.map((step, index) => ( +
+ {/* Main step with circle */} +
+
+ {isDarkStepComplete(index) && ( + + + + )} +
+ +
+
+ + {step.title} + + {step.optional && ( + + Optional + + )} + {step.notice && ( + + {step.notice} + + )} +
+ + {step.description && ( +
+ {step.description} +
+ )} +
+
+
+ ))} +
+
+
+
+
+
+ ); +}; + +export default DevelopmentSteps; diff --git a/src/pages/Home/Editing.tsx b/src/pages/Home/Editing.tsx new file mode 100644 index 0000000..a27a8ad --- /dev/null +++ b/src/pages/Home/Editing.tsx @@ -0,0 +1,95 @@ +import React from "react"; + +import editingImg from "~/assets/editing3.png"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +const Editing: React.FC = () => { + const features = [ + { + id: 1, + description: + "Darklang has a Language Server that provides real-time feedback, AI-powered completions, instant diagnostics, and easy access to language features. It wraps a lightweight VS Code extension for seamless integration and an intuitive coding experience.", + }, + { + id: 2, + description: + "Built entirely in Darklang, the language server follows the Language Server Protocol (LSP), making it easy to expand support to more editors so you can use Darklang in your favourite development environment.", + }, + { + id: 3, + description: + "The Language Server is designed to be flexible, so users can configure it to fit their needs", + }, + ]; + + return ( +
+
+
+
+
+ + Powerful, Familiar, and Extensible editing + +

+ Edit code in your preferred environment—whether it's your local + editor, a browser-based IDE, or directly in the CLI. This is + made possible by Darklang's Language Server: +

+
+ + {features.map(feature => ( +
+
+
+ + + +
+
+
+

+ {feature.description} +

+
+
+ ))} + + +
+ +
+ Darklang Editor Environment +
+
+
+
+ ); +}; + +export default Editing; diff --git a/src/pages/Home/GradualStaticTyping.tsx b/src/pages/Home/GradualStaticTyping.tsx new file mode 100644 index 0000000..8c7df59 --- /dev/null +++ b/src/pages/Home/GradualStaticTyping.tsx @@ -0,0 +1,63 @@ +import React from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +type FeaturePoint = { + text: string; +}; + +const GradualStaticTyping: React.FC = () => { + const featurePoints: FeaturePoint[] = [ + { text: "While prototyping, just run code until you hit a type error" }, + { + text: "After prototyping, run the full type checker to gain confidence your whole program works", + }, + { + text: "! and ? operators allow easy error handling while you prototype", + }, + { + text: "Automatic refactoring converts ! into proper error handling", + }, + { text: "Full type-checking hints in VSCode or in LSP editors" }, + ]; + + return ( +
+
+ + Gradual Static Typing + + +

+ Gradual Static Typing allows running incomplete programs so you don't + need to ensure everything type checks when you're getting one path + working +

+ +
+ {/* Vertical line */} +
+ + {/* Feature points */} + {featurePoints.map((point, index) => ( +
+ {/* Circle marker */} +
+
+
+ + {/* Content */} +
+

+ {point.text} +

+
+
+ ))} +
+
+
+ ); +}; + +export default GradualStaticTyping; diff --git a/src/pages/Home/Hero.tsx b/src/pages/Home/Hero.tsx new file mode 100644 index 0000000..b16c05d --- /dev/null +++ b/src/pages/Home/Hero.tsx @@ -0,0 +1,40 @@ +import React from "react"; + +import Button from "../../common/ui/Button"; + +const Hero: React.FC = () => { + return ( +
+
+

+ Build above the cloud +

+ +

+ Darklang is an integrated language, framework, runtime, and editor for + building software— CLI scripts and REPLs, cloud apps, and more +

+ +

+ Write simple code that runs + everywhere. No setup.{" "} + Just code. +

+ + + + {/* GIF placeholder */} + {/*
*/} +
+
+ ); +}; + +export default Hero; diff --git a/src/pages/Home/LanguageFeatures.tsx b/src/pages/Home/LanguageFeatures.tsx new file mode 100644 index 0000000..d8104e5 --- /dev/null +++ b/src/pages/Home/LanguageFeatures.tsx @@ -0,0 +1,221 @@ +import React, { useState } from "react"; + +import SectionTitle from "../../common/ui/SectionTitle"; +import CodeDisplay from "../../common/ui/CodeDisplay"; + +interface CodeTabProps { + isActive: boolean; + label: string; + onClick: () => void; +} + +interface FeatureItemProps { + children: React.ReactNode; +} + +interface TabData { + id: string; + label: string; + code: string; +} + +const CodeTab: React.FC = ({ isActive, label, onClick }) => ( + +); + +const FeatureItem: React.FC = ({ children }) => ( +
+
+ + + + +
+
{children}
+
+); + +// Main Component +const LanguageFeatures: React.FC = () => { + // Tab data + const tabs: TabData[] = [ + { + id: "functional", + label: "Functional Style", + code: `// Simple types +type UserAction = + | Click of String + | Type of String + | Submit + +// Match patterns +let handleAction (action:UserAction) : String = + match action with + | Click button -> $"Button '{button}' clicked." + | Type input -> $"User typed: '{input}'" + | Submit -> "Form submitted!" + +let actions = [Click "Login"; Type "Hello"; Submit] + +// First-class functions +let logs = actions |> Stdlib.List.map handleAction + +// Immutable and composable +logs |> List.iter printLine`, + }, + { + id: "records", + label: "Records & Enums", + code: `// Record +type Url = { + scheme : HttpScheme + domain : String + port : UInt16 + path : String + query : Option +} + +// Enum (aka Variant, Sum Type, or Abstract Data Types) +type UrlError = +| InvalidScheme(String) +| EmptyDomain +| InvalidPort(Int64) +| Unparseable(msg:String, context:String) + +// Aliases are just shorthands +type UrlParseResult = Result`, + }, + { + id: "option", + label: "Option & Result types", + code: `// Option type instead of null +type Option<'v> = +| Some of 'v +| None + +let findUser (users: List) (id: int) : Option = + users |> List.tryFind (fun user → user.Id = id) + +// Result type instead of exceptions +type Result<'Ok, 'Err> = +| Ok of 'Ok +| Error of 'Err + +let findUser +(users: List) +(id: int) +: Result = + let user = users |> List.tryFind (fun user → user.Id = id) + match user with + | Some user → Ok user + | None → Error NotFound`, + }, + { + id: "unicode", + label: "Unicode-First", + code: `// All characters in Darklang represent Extended Grapheme +// Clusters. + +// Characters represent what you see on screen +String.length "hello" // 5 +String.length "👨‍👩‍👧‍👦" // 1`, + }, + ]; + + const features = [ + "Built-in immutability and strong type system", + "Garbage-collected", + "Unicode-first", + "Records and Enums for straightforward data modeling", + "Option and Result types keep errors explicit", + ]; + + const [activeTab, setActiveTab] = useState(tabs[0].id); + + // Get current tab code + const getCurrentTabCode = () => { + const tab = tabs.find(tab => tab.id === activeTab); + return tab ? tab.code : ""; + }; + + return ( +
+
+
+ {/* Left side */} +
+ + Functional, Composable, and Fun to use + + +

+ Darklang is a statically-typed functional language built for + simplicity and composability. No null, no unexpected exceptions + —just predictable code that's easy to write, read, and maintain. +

+ +
+ {features.map((feature, index) => ( + + {feature} + + ))} +
+
+ + {/* Right side */} +
+
+ {/* Tabs navigation */} +
+ {tabs.map(tab => ( + setActiveTab(tab.id)} + /> + ))} +
+ + {/* Code display area */} +
+
+ +
+
+
+
+
+
+
+ ); +}; + +export default LanguageFeatures; diff --git a/src/pages/Home/Newsletter.tsx b/src/pages/Home/Newsletter.tsx new file mode 100644 index 0000000..9f566ad --- /dev/null +++ b/src/pages/Home/Newsletter.tsx @@ -0,0 +1,146 @@ +import React, { useState, useRef } from "react"; + +import Button from "../../common/ui/Button"; + +interface NewsletterProps { + className?: string; +} + +const Newsletter: React.FC = () => { + const [error, setError] = useState(""); + const [isSubmitted, setIsSubmitted] = useState(false); + const formRef = useRef(null); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + // Reset error state + setError(""); + + const emailInput = document.getElementById( + "newsletterEmail", + ) as HTMLInputElement; + if (!emailInput?.value) { + setError("Please enter your email address"); + return; + } + + try { + const response = await fetch( + "https://ops-corpsite.builtwithdark.com/signup", + { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email: emailInput.value, + }), + }, + ); + + if (response.status === 200) { + setIsSubmitted(true); + } else { + setError("Error adding to waitlist"); + } + } catch (err) { + setError("Failed to subscribe. Please try again."); + console.error("Subscription error:", err); + } + }; + + return ( +
+
+
+
+

+ Send me project updates +

+

+ Get notified about new features, updates, Bug Fixes, project + milestones, and more +

+
+ + {!isSubmitted ? ( +
+
+
+ + {error && ( + + {error} + + )} +
+ +
+ +
+ + + + Monthly updates, no spam, unsubscribe anytime +
+
+ ) : ( +
+ Added to waitlist! + + + +
+ )} +
+
+
+ ); +}; + +export default Newsletter; diff --git a/src/pages/Home/PackageManager.tsx b/src/pages/Home/PackageManager.tsx new file mode 100644 index 0000000..913517f --- /dev/null +++ b/src/pages/Home/PackageManager.tsx @@ -0,0 +1,127 @@ +import React from "react"; + +import packageManagerImg from "~/assets/packageManager.png"; + +import SectionTitle from "../../common/ui/SectionTitle"; + +const PackageManager: React.FC = () => { + const features = [ + { + id: 1, + title: "No Install Step", + description: + "Built-in package management without npm-style installation processes or Python's painful package compatibility issues.", + }, + { + id: 2, + title: "Immutable", + description: + "Updates never overwrite existing code but create new versions with unique identifiers.", + }, + { + id: 3, + title: "Precise Package Item Control", + description: + "Only download and upgrade the specific package items you use.", + }, + { + id: 4, + title: "Source-Controlled Package Management", + description: "The package manager functions as a source repository.", + }, + { + id: 5, + title: "Smart Dependency Management", + description: + "Automated dependency upgrades, as we track deprecation status, and know what functions are pure and safe to update.", + }, + { + id: 6, + title: "Version Flexibility", + description: + "Different packages can rely on different versions of other packages.", + }, + { + id: 7, + title: "Parallel Versioning", + description: + "Use multiple versions of the same package item at once: allows testing new versions without having to change an entire package version, lowering risk.", + }, + { + id: 8, + title: "Effortless Pre-Release Sharing", + description: + "Share pre-release functions trivially, without contributors needing to check out your git repo or set up anything.", + }, + { + id: 9, + title: "Zero Overhead Workflow", + description: + "No need for uploads, releases or other synchronization. No git or GitHub required (but you can sync to GitHub if you prefer).", + }, + ]; + + return ( +
+
+ + Next-gen Package Manager + +
+

+ Darklang has a rather unique package manager built directly into the + runtime, where functions and types are individually versioned and + immutable, taking a lot of the hassle out of package management. +

+
+
+
+ {features.map(feature => ( +
+
+
+ + + + +
+
+
+

+ {feature.title} +

+

+ {feature.description} +

+
+
+ ))} +
+ +
+ Package Manager Architecture +
+
+
+
+ ); +}; + +export default PackageManager; diff --git a/src/pages/Home/TraceDrivenDevelopment.tsx b/src/pages/Home/TraceDrivenDevelopment.tsx new file mode 100644 index 0000000..01ec59c --- /dev/null +++ b/src/pages/Home/TraceDrivenDevelopment.tsx @@ -0,0 +1,185 @@ +import React from "react"; + +import { + HttpIcon, + WorkerIcon, + CronIcon, + CliIcon, + FnIcon, + MiscIcon, +} from "../../common/ui/Icons"; +import SectionTitle from "../../common/ui/SectionTitle"; +import { TraceCard } from "../../common/ui/Card"; + +const httpCodeSample = `Made less than a minute ago +request: { + body: { + info: "testinfo", + }, + fullBody:"{\\\"info\\\":\\\"testinfo\\\"}", + headers: { + accept: "*/*", + content-length: "37", + ... + } +}`; + +const fnCallCodeSample = `Made 4 minutes ago +getUserPaintings(userId) +▸ args: +"u-573829" +▸ returns: +[ +{ "id": "p-001", "title": "Mountain Sunset", "created": "2024-11-05" }, +{ "id": "p-002", "title": "Ocean Waves", "created": "2025-12-01" } +] +▸ duration: 47ms`; + +const cliCodeSample = `Made 3 minutes ago +$ npm run deploy --env=staging +stdout: +Deploying to staging environment... +✓ Building application (2.3s) +✓ Running tests (1.7s) +✓ Uploading assets (4.2s) +✓ Deployment complete (8.7s) +exit: 0`; + +const workerCodeSample = `Made 2 minutes ago +WORKER: media-processor +TASK_ID: wrk_8a72c9d3 +STATUS: completed +DURATION: 3.8s +RESULT: { +"processedFiles": 7, +"compressionRatio": 2.24 +}`; + +const cronCodeSample = `Made 25 minutes ago +JOB_ID: cron_93f721a5 +NAME: data-sync-production +SCHEDULE: */15 * * * * +STATUS: success +DURATION: 42.3s +RESULT: { "records_processed": 8427 }`; + +const miscCodeSample = `Create custom trace collectors +Made 17 minutes ago +EVENT: user.onboarding.completed +context: { +userId: "usr_27b391fe", +timestamp: "2025-04-18T15:28:13Z" +} +data: { +stepsCompleted: 4, +totalDuration: 462 +}`; + +const TraceDrivenDevelopment: React.FC = () => { + return ( +
+
+
+ {/* Left Side Content */} +
+ + Development with Real Data + + +

+ The best way to debug and refactor code is with the help of{" "} + + real user data + + . As your code executes, whether{" "} + + locally + {" "} + or in the{" "} + + cloud + + , traces are captured and made available in your development + workflow, making it easier to refactor code and debug issues. +

+ +

+ Traces are captured centrally in the package manager, stored + locally first, and securely available in your editing environment + - you control when and if they sync. +

+ + + See how traces work with real examples → + +
+ + {/* Right Side Stacked Cards*/} +
+
+ {/* Left column of cards */} + +
+ } + description="Capture and analyze HTTP requests and responses in real-time. Debug API integrations with complete request data." + codeSample={httpCodeSample} + color="blue" + > + + } + description="Inspect function inputs, outputs, and performance metrics. Debug complex operations with detailed traces." + codeSample={fnCallCodeSample} + color="magenta" + > + + } + description="Track CLI operations with detailed input and output records. Monitor script execution, environment variables, and command results for easy debugging." + codeSample={cliCodeSample} + color="purple" + > +
+ + {/* Right column of cards */} +
+ } + description="Track and monitor background workers and their execution. Observe task processing in real-time." + codeSample={workerCodeSample} + color="taupe" + > + + } + description="Monitor scheduled tasks and their execution results. Ensure automation runs correctly with real data." + codeSample={cronCodeSample} + color="orange" + > + + } + description="Customize your own trace types and visualizations. Monitor any aspect of your application with flexible data collection." + codeSample={miscCodeSample} + color="gray" + > +
+
+
+
+
+
+ ); +}; + +export default TraceDrivenDevelopment; diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx new file mode 100644 index 0000000..d7fb087 --- /dev/null +++ b/src/pages/Home/index.tsx @@ -0,0 +1,37 @@ +import Hero from "./Hero"; +import DevelopmentSteps from "./DevelopmentSteps"; +import BackendFeatures from "./BackendFeatures"; +import LanguageFeatures from "./LanguageFeatures"; +import AsyncRuntime from "./AsyncRuntime"; +import GradualStaticTyping from "./GradualStaticTyping"; +import PackageManager from "./PackageManager"; +import TraceDrivenDevelopment from "./TraceDrivenDevelopment"; +import Editing from "./Editing"; +import CLI from "./CLI"; +import DeploylessCloud from "./DeploylessCloud"; +import DesignedForGenAI from "./DesignedForGenAI"; +import Newsletter from "./Newsletter"; +import BlogPostsExample from "./BlogPostsExample"; + +const Home = () => { + return ( + <> + + + + + + + + + + + + + + + + ); +}; + +export default Home; diff --git a/src/pages/Language/index.tsx b/src/pages/Language/index.tsx new file mode 100644 index 0000000..023649e --- /dev/null +++ b/src/pages/Language/index.tsx @@ -0,0 +1,70 @@ +import React from "react"; + +const Language: React.FC = () => { + return ( + +
+
+        it's an ML-style language yay
+      
+ +

+ Darklang is a statically-typed, functional/imperative hybrid programming language designed primarily for building cloud-based backend services. Its functional aspects draw inspiration from languages like OCaml, Elm, and Rust, emphasizing simplicity, type safety, and productivity while avoiding complex functional programming concepts like monads or category theory. +

+ +

+ Immutability: + Darklang embraces immutability, a core functional programming principle. Values in Darklang are immutable by default, eliminating race conditions in concurrent execution and making programs easier to reason about. +

+ +

+ No Exceptions, Use of Results and Options: + Instead of exceptions, which can complicate reasoning in functional programming, Darklang uses Result and Option types to handle errors and optional values. This approach, inspired by languages like Rust and OCaml, ensures explicit error handling and avoids issues associated with nulls or unchecked exceptions. +

+ +

+ First-Class Functions and Pipelines: + Darklang supports first-class functions, enabling functions to be passed as arguments, returned from other functions, and assigned to variables, a standard feature in functional languages. + It makes heavy use of pipelines (similar to F# or Elm), allowing developers to chain function calls in a readable, declarative way. For example, operations like List::map are used to transform collections functionally +

+ +

+ Implicit Returns: + Like many functional languages (e.g., Elm or Haskell), Darklang uses implicit returns, where the last expression in a function is automatically its return value. This reduces boilerplate and aligns with functional programming’s focus on expressions over statements. +

+ +

+ Simple Type System with Records and Enums: + Darklang employs a straightforward type system based on Records and Enums (also known as variants or sum types), similar to Rust, Elm, or OCaml. These types are expressive enough to model complex data structures while remaining simpler than object-oriented class hierarchies. + For example, a Url type might be defined as a record with fields like scheme, domain, and port, while a UrlError enum could represent possible errors like InvalidScheme or EmptyDomain. This approach avoids the complexity of inheritance and aligns with functional programming’s preference for algebraic data types. +

+ +

+ Functional/Imperative Hybrid: + While primarily functional, Darklang is described as a functional/imperative hybrid, drawing from OCaml, Elm, and Rust rather than purely functional languages like Haskell. This hybrid nature makes it accessible to developers familiar with imperative or object-oriented languages, avoiding esoteric functional concepts like monads, lenses, or combinators. + The language prioritizes developer productivity by allowing imperative-style code where needed, but its functional core ensures type safety and immutability. +

+ +

+ Asynchronous Programming Without await: + Darklang’s runtime is fully asynchronous, but it avoids the explicit await keywords common in languages like JavaScript or TypeScript. Instead, it uses data dependencies to manage concurrency, a functional approach that ensures operations wait for their inputs without exposing threading complexity. + This design eliminates race conditions (due to immutability) and simplifies concurrent programming, aligning with functional programming’s emphasis on declarative concurrency models. +

+ +

+ Unicode-Aware Strings: + Darklang’s string handling is designed for modern applications, using Extended Grapheme Clusters to represent characters (e.g., emojis like 👨‍👩‍👦‍👦 are treated as single characters). This functional approach to string representation avoids the pitfalls of byte-based or UTF-16 strings in older languages, ensuring predictable behavior in text processing. +

+ +

+ Reliability: Static typing and immutability ensure that compiled code is robust, a critical feature for cloud backends. + Concurrency: Immutability and data-driven async execution simplify concurrent programming, a key requirement for scalable backend services. + Productivity: Features like pipelines, implicit returns, and gradual typing make functional programming accessible and efficient, aligning with Darklang’s goal of simplifying backend development. +

+ +
+ + ); +}; + +export default Language; diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx new file mode 100644 index 0000000..832eac3 --- /dev/null +++ b/src/pages/NotFound.tsx @@ -0,0 +1,31 @@ +import { Link } from "react-router-dom"; + +const NotFound = () => { + return ( +
+

404

+

+ Page Not Found +

+

+ The page you're looking for doesn't exist or has been moved. +

+
+ + Go Home + + + Visit Docs + +
+
+ ); +}; + +export default NotFound; diff --git a/src/pages/Roadmap.tsx b/src/pages/Roadmap.tsx new file mode 100644 index 0000000..d1810e7 --- /dev/null +++ b/src/pages/Roadmap.tsx @@ -0,0 +1,65 @@ +const Roadmap = () => { + return ( +
+

+ Darklang Roadmap +

+ +
+

+ At Darklang, we're committed to building a powerful yet simple + platform for backend development. Our roadmap outlines our vision for + the future and the features we're working on. +

+ +
+
+
+ +
    +
  • Enhanced debugging tools with time-travel capabilities
  • +
  • Extended package management system
  • +
  • Performance optimizations for large-scale applications
  • +
  • New UI components library
  • +
+
+ +
+
+ +
    +
  • Advanced deployment strategies (canary, blue-green)
  • +
  • AI-assisted coding features
  • +
  • Enhanced data visualization tools
  • +
  • Expanded third-party service integrations
  • +
+
+ +
+
+ +
    +
  • Multi-region deployment support
  • +
  • Advanced monitoring and observability tools
  • +
  • Expanded language features for complex applications
  • +
  • Large-scale enterprise features and support
  • +
+
+
+ +
+

Help Shape Our Future

+

+ We believe in building in public and with our community. Have + suggestions or feature requests? We'd love to hear from you! +

+ +
+
+
+ ); +}; + +export default Roadmap; diff --git a/src/pages/TraceDriven/index.tsx b/src/pages/TraceDriven/index.tsx new file mode 100644 index 0000000..1503bfc --- /dev/null +++ b/src/pages/TraceDriven/index.tsx @@ -0,0 +1,34 @@ +import React from "react"; + +const TraceDriven: React.FC = () => { + return ( +

+ Traces are a core feature of Darklang that enable developers to work with live request data to build and debug applications efficiently. + Acting as an "omniscient debugger" traces provide complete visibility into the state of an application at any point in time, allowing developers + to see exactly what data flows through their code and how it behaves without needing traditional debugging tools like print statements or external loggers. + + Traces power Trace-Driven Development, a workflow where you start by sending requests to non-existent endpoints. + Darklang records those traces, which you then use to write code that handles real inputs. + This approach ensures code is developed with actual data, reducing guesswork and errors. + + Traces are records of HTTP requests (or other events) made to a Darklang app. Whether your code runs locally or in the cloud, + traces automatically capture inputs and intermediate values during execution for: + - HTTP handlers + - Worker `emit`s + - Function calls + - CRON responses + - CLI application calls + + A trace includes: + - Request Inputs: The full HTTP request, including headers, query parameters, body and metadata. + - Intermediate Values: Values computed during the execution of a handler, such as the results of expressions or function calls. + - Live Values: The evaluated results of expressions for a selected traceThese update in real-time as you write code. + - Return Values: The final output of a handler + + All traces are securely and centrally captured in the package manager, and made available in your editing environment. + This approach streamlines debugging, improves accuracy, and makes refactoring safer—all by letting real data guide the development process. +

+ ); +}; + +export default TraceDriven; diff --git a/src/pages/TypeChecking/index.tsx b/src/pages/TypeChecking/index.tsx new file mode 100644 index 0000000..e93c8f7 --- /dev/null +++ b/src/pages/TypeChecking/index.tsx @@ -0,0 +1,40 @@ +import React from "react"; + +const TypeChecking: React.FC = () => { + return ( +
+
+        Runtime is done-ish
+        Parse-time is barely there
+      
+ +

+ Type checking:
+ - Darklang is fully statically typed with Gradual Flexibility, ensuring that types are checked at compile time to catch errors early. This helps developers ensure that changes across large programs are safe, particularly for refactoring or scaling systems
+ - Unlike traditional functional languages where the entire program must compile, Darklang employs gradual static typing. This allows incomplete or partially typed code to run, enabling developers to prototype quickly without ensuring every part of the program type-checks immediately
+ - Darklang uses small compilation units, meaning that type checking is localized to specific parts of the program, such as a single HTTP route. This reduces the scope of type changes needed when prototyping or making small modifications
+ - Instead of modifying existing types, developers create a copy of a type, make changes, and test them. Once validated, semi-automated tooling helps propagate these changes across the program, minimizing the effort required for large-scale type updates.
+ - The language supports Option and Result types for error handling, replacing nulls and exceptions to avoid common pitfalls like null pointer errors
+ - Types and functions in Darklang are versioned and immutable, ensuring that changes don’t break existing code. This is particularly useful in the package manager, where types and functions are individually versioned
+ - When updating types, developers can test new versions without affecting the entire program, and tooling assists in migrating to the new type once it’s finalized.
+ - Future plans include implementing an at-rest/static checker to perform comprehensive type checking, including preventing invalid operations (e.g., adding a String and an Int). This will leverage Darklang’s access to trace data for advanced diagnostics
+ + Benefits of Darklang’s Type Checking
+ + - Safety: Static typing ensures type mismatches are caught early, reducing runtime errors and making large-scale changes safer
+ - Productivity: Small compilation units and gradual typing allow rapid prototyping, akin to dynamic languages, while retaining static typing benefits
+ - Error Handling: The Option/Result types simplify error management, eliminating the need for exceptions and reducing null-related bugs
+ - Maintainability: Versioned types and editor integration make refactoring and maintaining code easier, especially in evolving projects
+ - Diagnostics: Integration with trace data provides unique insights into type-related issues, improving debugging and development efficiency
+ - Scalability: Versioned types and small compilation units make it easier to scale and refactor backends as projects grow
+

+ + for more content inspo:
+ - https://blog.darklang.com/real-problems-with-functional-languages/amp/
+ - https://blog.darklang.com/an-overdue-status-update/ + +
+ ); +}; + +export default TypeChecking; diff --git a/src/pages/template.tsx b/src/pages/template.tsx new file mode 100644 index 0000000..8bed605 --- /dev/null +++ b/src/pages/template.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +const TODO: React.FC = () => { + return ( +

+ TODO +

+ ); +}; + +export default TODO; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index cc7eeb4..0000000 --- a/tailwind.config.js +++ /dev/null @@ -1,50 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ["./public/*.{html,js}", "./public/**/*.{html,js}"], - theme: { - fontFamily: { - body: ["Inter", "sans-serif"], - "League-Gothic": ["League Gothic", "sans-serif"], - Assistant: ["Assistant", "sans-serif"], - Quicksand: ["Quicksand", "sans-serif"], - FiraCode: ["Fira Code", "monospace"], - }, - listStyleType: { - none: "none", - disc: "disc", - decimal: "decimal", - square: "square", - roman: "upper-roman", - }, - extend: { - colors: { - "light-background": "#FAFAFA", - purple: "#955B9F", - blue: "#747AB9", - "dark-gray": "#2F2F2F", - "code-background": "#F5F4F1", - "cli-background": "#262626", - // classic colors - "classic-green": "#A1B56C", - "classic-brown": "#A1887F", - "classic-yellow": "#E6BD81", - "classic-blue": "#86C1B9", - "classic-purple": "#B278FF", - "classic-pink": "#F56FF0", - }, - flex: { - 2: "2 2 0%", - }, - - animation: { - shine: "shine 1s linear", - }, - keyframes: { - shine: { - "100%": { left: "125%" }, - }, - }, - }, - }, - plugins: [require("@tailwindcss/line-clamp")], -}; diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..358ca9b --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..318c218 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["src/*"], + } + }, + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..db0becc --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..169f2cd --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; +import { resolve } from "path"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), tailwindcss()], + resolve: { + alias: { + '~': resolve(process.cwd(), 'src'), + }, + }, + build: { + minify: true, + rollupOptions: { + output: { + manualChunks: { + vendor: ["react", "react-dom", "react-router-dom"], + ui: ["highlight.js", "tailwindcss"], + }, + }, + }, + }, +});