diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0c5e9d0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +spock-website/tests/__screenshots__/**/*.png filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 0000000..ac78283 --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,55 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: [ 'main', 'master' ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: 'pages' + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./spock-website + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'npm' + cache-dependency-path: spock-website/package-lock.json + - name: Install dependencies + run: npm ci + - name: Build + run: npm run build + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload dist folder + path: './spock-website/dist' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/update-reference-screenshots.yaml b/.github/workflows/update-reference-screenshots.yaml new file mode 100644 index 0000000..5cf706e --- /dev/null +++ b/.github/workflows/update-reference-screenshots.yaml @@ -0,0 +1,45 @@ +name: Deploy static content to Pages + +on: + workflow_dispatch: + +permissions: + contents: write + +jobs: + update-screenshots: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./spock-website + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: true # Download LFS files for screenshots + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'npm' + cache-dependency-path: spock-website/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Run Playwright Tests updating snapshots + run: npx playwright test --update-snapshots + + - name: Commit updated snapshots + run: | + git config user.email "dev@forum.spockframework.org" + git config user.name "Spock Framework Robot" + git add tests/__screenshots__/ + if [[ -n "$(git status --porcelain)" ]]; then + echo "::set-output name=has_changes::true" + git commit -m "Update reference screenshots" + git push origin HEAD:${{ github.ref_name }} + else + echo "::set-output name=has_changes::false" + fi diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml new file mode 100644 index 0000000..25bca4c --- /dev/null +++ b/.github/workflows/verify.yaml @@ -0,0 +1,74 @@ +name: Verify PR build + +on: + pull_request: + branches: [ 'main', 'master' ] + +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./spock-website + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Verify LFS files + run: | + git lfs install + git lfs fsck --pointers HEAD + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'npm' + cache-dependency-path: spock-website/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Upload artifact + uses: 'actions/upload-artifact@v4' + with: + name: 'gh-pages-preview' + path: './spock-website/dist' + + verify: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./spock-website + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: true # Download LFS files for screenshots + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'npm' + cache-dependency-path: spock-website/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Run Playwright Tests + run: npx playwright test + + - name: Upload Test Results (optional) + uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: spock-website/playwright-report/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d68c6f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +.idea/ +node_modules/ +dist/ +playwright-report/ +test-results/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/compositor.json b/compositor.json deleted file mode 100644 index ef69af2..0000000 --- a/compositor.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "name": "spockframework/spockframework.github.io", - "version": "0.1.4", - "libraries": { - "xv": "^1.1.21" - }, - "title": "Spock", - "branch": "", - "style": { - "name": "Default", - "componentSet": { - "nav": "nav/BasicNav", - "header": "header/BannerHeader", - "article": "article/BasicArticle", - "footer": "footer/BasicFooter" - }, - "fontFamily": "-apple-system, BlinkMacSystemFont, sans-serif", - "fontWeight": 400, - "bold": 600, - "lineHeight": 1.5, - "typeScale": [ - 72, - 48, - 24, - 20, - 16, - 14, - 12 - ], - "monospace": "Menlo, monospace", - "heading": { - "fontFamily": null, - "fontStyle": null, - "fontWeight": 600, - "lineHeight": 1.25, - "textTransform": null, - "letterSpacing": null, - "h0": {}, - "h1": {}, - "h2": {}, - "h3": {}, - "h4": {}, - "h5": {}, - "h6": {} - }, - "alternativeText": {}, - "space": [ - 0, - 8, - 16, - 32, - 48, - 64, - 96 - ], - "layout": { - "maxWidth": 1024, - "centered": false - }, - "colors": { - "text": "#111", - "background": "#fff", - "primary": "#08e", - "secondary": "#059", - "highlight": "#e08", - "border": "#ddd", - "muted": "#eee" - }, - "border": { - "width": 1, - "radius": 2 - }, - "link": {}, - "button": { - "hover": { - "boxShadow": "inset 0 0 0 999px rgba(0, 0, 0, .125)" - } - }, - "input": {}, - "body": { - "margin": 0 - }, - "breakpoints": { - "xs": "@media screen and (max-width:40em)", - "sm": "@media screen and (min-width:40em)", - "md": "@media screen and (min-width:52em)", - "lg": "@media screen and (min-width:64em)" - } - }, - "content": [ - { - "component": "header", - "heading": "Spock", - "subhead": "the enterprise ready specification framework", - "children": [ - { - "component": "ui/TweetButton", - "text": "spockframework.github.io: Spock project homepage", - "url": null - }, - { - "component": "ui/GithubButton", - "user": "spockframework", - "repo": "spockframework.github.io" - } - ], - "links": [ - { - "href": "http://docs.spockframework.org/", - "text": "Documentation" - }, - { - "href": "http://github.spockframework.org/", - "text": "Source" - }, - { - "href": "http://issues.spockframework.org/", - "text": "Issues" - }, - { - "href": "http://forum.spockframework.org/", - "text": "Forum" - } - ], - "slug": "" - }, - { - "component": "article", - "metadata": { - "source": "github.readme" - }, - "html": "<h2>What is it?</h2>\n<p>Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. Spock is inspired from <a href=\"http://www.junit.org/\">JUnit</a>, <a href=\"http://rspec.info/\">RSpec</a>, <a href=\"http://www.jmock.org/\">jMock</a>, <a href=\"http://www.mockito.org\">Mockito</a>, <a href=\"http://groovy.codehaus.org/\">Groovy</a>, <a href=\"http://www.scala-lang.org/\">Scala</a>, <a href=\"http://en.wikipedia.org/wiki/Vulcans\">Vulcans</a>, and other fascinating life forms.</p>\n<h2>How Do I Get Started?</h2>\n<p>Read ten reasons why Spock is for you, run your first spec in <a href=\"http://meetspock.appspot.com/?id=9001\">Spock Web Console</a>, fork the <a href=\"https://github.com/spockframework/spock-example\">spock-example</a> project, learn how to write a specification, or dive into the <a href=\"http://docs.spockframework.org\">reference documentation</a>.</p>\n<h2>Install</h2>\n<h3>with Gradle</h3>\n<pre><span class=\"hljs-selector-tag\">testCompile</span> "<span class=\"hljs-selector-tag\">org</span><span class=\"hljs-selector-class\">.spockframework</span><span class=\"hljs-selector-pseudo\">:spock-core</span><span class=\"hljs-selector-pseudo\">:1.1-groovy-2.4-rc-2"</span></pre><h3>with Maven:</h3>\n<pre><span class=\"hljs-tag\"><<span class=\"hljs-name\">dependency</span>></span>\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">groupId</span>></span>org.spockframework<span class=\"hljs-tag\"></<span class=\"hljs-name\">groupId</span>></span>\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">artifactId</span>></span>spock-core<span class=\"hljs-tag\"></<span class=\"hljs-name\">artifactId</span>></span>\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">version</span>></span>1.1-groovy-2.4-rc-2<span class=\"hljs-tag\"></<span class=\"hljs-name\">version</span>></span>\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">scope</span>></span>test<span class=\"hljs-tag\"></<span class=\"hljs-name\">scope</span>></span>\n<span class=\"hljs-tag\"></<span class=\"hljs-name\">dependency</span>></span></pre><h2>Where Are The Docs?</h2>\n<ul>\n<li>Reference Documentation: <a href=\"http://docs.spockframework.org\">http://docs.spockframework.org</a></li>\n<li>Wiki (old): <a href=\"http://wiki.spockframework.org\">http://wiki.spockframework.org</a></li>\n<li>Javadoc: <a href=\"http://javadoc.spockframework.org/latest\">http://javadoc.spockframework.org/latest</a></li>\n</ul>\n<h2>How Can I Get Involved?</h2>\n<ul>\n<li>Source Code: <a href=\"http://github.spockframework.org\">http://github.spockframework.org</a></li>\n<li>Issue Tracker: <a href=\"http://issues.spockframework.org\">http://issues.spockframework.org</a></li>\n<li>Discussion Forum: <a href=\"http://forum.spockframework.org\">http://forum.spockframework.org</a></li>\n<li>Continuous Build: <a href=\"http://builds.spockframework.org\">http://builds.spockframework.org</a></li>\n</ul>\n<h3>Supporters</h3>\n<p>Thanks to JetBrains for providing <a href=\"http://www.jetbrains.com/idea/\">IDEA</a> and <a href=\"http://www.jetbrains.com/teamcity/\">TeamCity</a> licenses.</p>\n<p>YourKit is kindly supporting open source projects with its full-featured Java Profiler.</p>\n<p>YourKit, LLC is the creator of innovative and intelligent tools for profiling\nJava and .NET applications. Take a look at YourKit's leading software products:\n<a href=\"http://www.yourkit.com/java/profiler/index.jsp\">YourKit Java Profiler</a> and\n<a href=\"http://www.yourkit.com/.net/profiler/index.jsp\">YourKit .NET Profiler</a>.</p>\n" - }, - { - "component": "footer", - "links": [ - { - "href": "https://github.com/spockframework/spock", - "text": "GitHub" - }, - { - "href": "https://github.com/spockframework/spock/issues", - "text": "Issues" - }, - { - "href": "http://forum.spockframework.org/", - "text": "Forum" - }, - { - "href": "http://docs.spockframework.org/", - "text": "Documentation" - } - ], - "heading": "" - } - ] -} \ No newline at end of file diff --git a/index.html b/index.html index ac55cee..bfe7528 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,415 @@ -<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Spock</title><style>*{box-sizing:border-box}.cxs-96960423 pre .hljs-literal{color:#08e}.cxs-799160745{font-size:48px}.cxs-3954183383{font-size:24px}.cxs-857983649 a:hover{text-decoration:underline}.cxs-3377994344{}.cxs-3377994344:hover{box-shadow:inset 0 0 0 999px rgba(0, 0, 0, .125)}.cxs-96960423{}.cxs-96960423 h1{font-weight:600;line-height:1.25;font-size:48px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h1 h0{}.cxs-96960423 h1 h1{}.cxs-96960423 h1 h2{}.cxs-96960423 h1 h3{}.cxs-96960423 h1 h4{}.cxs-96960423 h1 h5{}.cxs-96960423 h1 h6{}.cxs-96960423 h2{font-weight:600;line-height:1.25;font-size:24px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h2 h0{}.cxs-96960423 h2 h1{}.cxs-96960423 h2 h2{}.cxs-96960423 h2 h3{}.cxs-96960423 h2 h4{}.cxs-96960423 h2 h5{}.cxs-96960423 h2 h6{}.cxs-96960423 h3{font-weight:600;line-height:1.25;font-size:20px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h3 h0{}.cxs-96960423 h3 h1{}.cxs-96960423 h3 h2{}.cxs-96960423 h3 h3{}.cxs-96960423 h3 h4{}.cxs-96960423 h3 h5{}.cxs-96960423 h3 h6{}.cxs-96960423 h4{font-weight:600;line-height:1.25;font-size:16px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h4 h0{}.cxs-96960423 h4 h1{}.cxs-96960423 h4 h2{}.cxs-96960423 h4 h3{}.cxs-96960423 h4 h4{}.cxs-96960423 h4 h5{}.cxs-96960423 h4 h6{}.cxs-96960423 h5{font-weight:600;line-height:1.25;font-size:14px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h5 h0{}.cxs-96960423 h5 h1{}.cxs-96960423 h5 h2{}.cxs-96960423 h5 h3{}.cxs-96960423 h5 h4{}.cxs-96960423 h5 h5{}.cxs-96960423 h5 h6{}.cxs-96960423 h6{font-weight:600;line-height:1.25;font-size:12px;margin-top:32px;margin-bottom:8px}.cxs-96960423 h6 h0{}.cxs-96960423 h6 h1{}.cxs-96960423 h6 h2{}.cxs-96960423 h6 h3{}.cxs-96960423 h6 h4{}.cxs-96960423 h6 h5{}.cxs-96960423 h6 h6{}.cxs-96960423 p{overflow-x:auto;margin-top:0px;margin-bottom:16px}.cxs-96960423 code{font-family:Menlo, monospace;font-size:14px;padding:4px;background-color:#eee;border-radius:2px}.cxs-96960423 pre{font-family:Menlo, monospace;font-size:14px;overflow-x:auto;padding:16px;margin-top:8px;margin-bottom:32px;background-color:#eee;border-radius:2px}.cxs-96960423 pre .hljs-keyword{color:#08e}.cxs-96960423 pre .hljs-built_in{color:#059}.cxs-96960423 pre .hljs-type{color:#059}.cxs-857983649 a{color:#05a}.cxs-96960423 pre .hljs-number{color:#e08}.cxs-96960423 pre .hljs-regexp{color:#08e}.cxs-96960423 pre .hljs-string{color:#059}.cxs-96960423 pre .hljs-subst{color:#059}.cxs-96960423 pre .hljs-symbol{color:#08e}.cxs-96960423 pre .hljs-class{color:#08e}.cxs-96960423 pre .hljs-function{color:#e08}.cxs-96960423 pre .hljs-title{color:#08e}.cxs-96960423 pre .hljs-params{color:#059}.cxs-96960423 pre .hljs-comment{color:#059}.cxs-96960423 pre .hljs-doctag{color:#059}.cxs-96960423 pre .hljs-meta{color:#059}.cxs-96960423 pre .hljs-meta-keyword{color:#08e}.cxs-96960423 pre .hljs-meta-string{color:#08e}.cxs-96960423 hr{margin-top:48px;margin-bottom:48px;border:0px;border-bottom-style:solid;border-bottom-width:1px;border-bottom:2px solid #ddd}.cxs-96960423 table{border-collapse:separate;border-spacing:0px;max-width:100%;width:100%}.cxs-96960423 th{text-align:left;line-height:inherit;vertical-align:bottom}.cxs-96960423 td{vertical-align:top;line-height:inherit}.cxs-96960423 img{max-width: 100%;height: auto;margin-top:16px;margin-bottom:16px}.cxs-96960423 a{color:#08e;text-decoration: none}.cxs-96960423 a:hover{text-decoration:underline}.cxs-96960423 ul{padding-left:32px;margin-top:0px;margin-bottom:16px}.cxs-857983649{}.cxs-857983649 h1{font-weight:700;letter-spacing:-0.01em;font-size:24px;margin-top:48px;margin-bottom:48px;border-bottom-width:4px;border-bottom-style:solid}.cxs-857983649 img{max-width: 100%;height: auto;margin-top:16px;margin-bottom:16px}.cxs-857983649 h2{font-weight:700;letter-spacing:-0.01em;font-size:24px;margin-top:48px;margin-bottom:48px;border-bottom-width:4px;border-bottom-style:solid}.cxs-857983649 td{vertical-align:top;line-height:inherit}.cxs-857983649 h3{font-weight:700;letter-spacing:-0.01em;font-size:20px;margin-top:48px;margin-bottom:48px;border-bottom-width:2px;border-bottom-style:solid}.cxs-857983649 th{text-align:left;line-height:inherit;vertical-align:bottom}.cxs-857983649 h4{font-weight:700;letter-spacing:-0.01em;font-size:20px;margin-top:32px;margin-bottom:8px}.cxs-857983649 h5{font-weight:700;letter-spacing:-0.01em;font-size:20px;margin-top:32px;margin-bottom:8px}.cxs-857983649 h6{font-weight:700;letter-spacing:-0.01em;font-size:20px;margin-top:32px;margin-bottom:8px}.cxs-857983649 p{overflow-x:auto;max-width:40em;margin-top:0px;margin-bottom:16px}.cxs-857983649 code{font-family:Menlo, monospace;font-size:14px;color:#05a}.cxs-857983649 pre{font-family:Menlo, monospace;font-size:14px;overflow-x:auto;padding-top:16px;padding-bottom:16px;margin-top:32px;margin-bottom:32px;border-top:1px solid;border-bottom:1px solid}.cxs-857983649 pre .hljs-keyword{color:#05a}.cxs-857983649 pre .hljs-built_in{color:#444}.cxs-857983649 pre .hljs-type{color:#444}.cxs-857983649 pre .hljs-literal{color:#05a}.cxs-857983649 pre .hljs-number{color:#f30}.cxs-857983649 pre .hljs-regexp{color:#05a}.cxs-857983649 pre .hljs-string{color:#444}.cxs-857983649 pre .hljs-subst{color:#444}.cxs-857983649 pre .hljs-symbol{color:#05a}.cxs-857983649 pre .hljs-class{color:#05a}.cxs-857983649 pre .hljs-function{color:#f30}.cxs-857983649 pre .hljs-title{color:#05a}.cxs-857983649 pre .hljs-params{color:#444}.cxs-857983649 pre .hljs-comment{color:#444}.cxs-857983649 pre .hljs-doctag{color:#444}.cxs-857983649 pre .hljs-meta{color:#444}.cxs-857983649 pre .hljs-meta-keyword{color:#05a}.cxs-857983649 pre .hljs-meta-string{color:#05a}.cxs-857983649 hr{margin-top:48px;margin-bottom:48px;border:0px;border-bottom:2px solid}.cxs-857983649 table{border-collapse:separate;border-spacing:0px;max-width:100%;width:100%}.cxs-857983649 ul{list-style:square inside;padding-left:0px;margin-top:0px;margin-bottom:32px}@media screen and (min-width:52em) { .cxs-857983649 h3{font-size:24px} }@media screen and (min-width:52em) { .cxs-857983649 h2{font-size:48px} }@media screen and (min-width:52em) { .cxs-857983649 h1{font-size:48px} }@media screen and (min-width: 52em) { .cxs-799160745{font-size:72px} }@media screen and (min-width: 52em) { .cxs-3954183383{} }</style></head><body style="margin:0;"><div class="Xv" style="font-family:-apple-system, BlinkMacSystemFont, sans-serif;font-weight:400;line-height:1.5;color:#111;background-color:#fff;"><header class="BannerHeader" style="display:flex;align-items:center;justify-content:center;text-align:left;min-height:100vh;color:white;background-color:#111;background-image:url(undefined);background-size:cover;background-position:center;"><div style="box-sizing:border-box;width:100%;max-width:1024px;margin-left:auto;margin-right:auto;padding-top:48px;padding-bottom:48px;padding-left:32px;padding-right:32px;"><h1 class="cxs-799160745" style="box-sizing:border-box;font-weight:600;line-height:1.25;h0:[object Object];h1:[object Object];h2:[object Object];h3:[object Object];h4:[object Object];h5:[object Object];h6:[object Object];margin:0;">Spock</h1><h2 class="cxs-3954183383" style="box-sizing:border-box;font-weight:600;line-height:1.25;h0:[object Object];h1:[object Object];h2:[object Object];h3:[object Object];h4:[object Object];h5:[object Object];h6:[object Object];margin:0;">the enterprise ready specification framework</h2><div style="box-sizing:border-box;margin-left:-16px;margin-right:-16px;"><a href="https://docs.spockframework.org/" class="cxs-3377994344" style="box-sizing:border-box;font-family:inherit;font-size:inherit;font-weight:600;line-height:1.5;display:inline-block;margin:16px;padding-top:8px;padding-bottom:8px;padding-left:16px;padding-right:16px;border-width:1px;border-style:solid;border-color:transparent;cursor:pointer;border-radius:2px;color:#fff;background-color:#08e;text-decoration:none;hover:[object Object];">Documentation</a><a href="https://github.com/spockframework/spock" class="cxs-3377994344" style="box-sizing:border-box;font-family:inherit;font-size:inherit;font-weight:600;line-height:1.5;display:inline-block;margin:16px;padding-top:8px;padding-bottom:8px;padding-left:16px;padding-right:16px;border-width:1px;border-style:solid;border-color:transparent;cursor:pointer;border-radius:2px;color:#fff;background-color:#08e;text-decoration:none;hover:[object Object];">Source</a><a href="https://github.com/spockframework/spock/issues" class="cxs-3377994344" style="box-sizing:border-box;font-family:inherit;font-size:inherit;font-weight:600;line-height:1.5;display:inline-block;margin:16px;padding-top:8px;padding-bottom:8px;padding-left:16px;padding-right:16px;border-width:1px;border-style:solid;border-color:transparent;cursor:pointer;border-radius:2px;color:#fff;background-color:#08e;text-decoration:none;hover:[object Object];">Issues</a><a href="https://gitter.im/spockframework/spock/" class="cxs-3377994344" style="box-sizing:border-box;font-family:inherit;font-size:inherit;font-weight:600;line-height:1.5;display:inline-block;margin:16px;padding-top:8px;padding-bottom:8px;padding-left:16px;padding-right:16px;border-width:1px;border-style:solid;border-color:transparent;cursor:pointer;border-radius:2px;color:#fff;background-color:#08e;text-decoration:none;hover:[object Object];">Chat</a><div style="display:table;clear:both;"></div></div><div style="box-sizing:border-box;margin-left:-8px;margin-right:-8px;padding-top:16px;padding-bottom:16px;"><iframe src="https://platform.twitter.com/widgets/tweet_button.html?text=spockframework.github.io%3A%20Spock%20project%20homepage&url=&via=&hashtags=&size=" height="20" allowtransparency="true" frameborder="0" scrolling="no" style="box-sizing:border-box;width:61px;overflow:hidden;margin:8px;"></iframe><iframe src="https://ghbtns.com/github-btn.html?type=star&count=true&user=spockframework&repo=spock&size=" height="20" frameborder="0" scrolling="no" style="box-sizing:border-box;width:100px;overflow:hidden;margin:8px;"></iframe><div style="display:table;clear:both;"></div></div></div></header><div class="cxs-96960423" style="box-sizing:border-box;max-width:1024px;margin-left:auto;margin-right:auto;padding-top:32px;padding-bottom:32px;padding-left:32px;padding-right:32px;"><article style="box-sizing:border-box;"><div><h2>What is it?</h2> -<p>Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. Spock is inspired from <a href="https://www.junit.org/">JUnit</a>, <a href="https://rspec.info/">RSpec</a>, <a href="http://www.jmock.org/">jMock</a>, <a href="https://site.mockito.org">Mockito</a>, <a href="https://groovy-lang.org/">Groovy</a>, <a href="https://www.scala-lang.org/">Scala</a>, <a href="https://en.wikipedia.org/wiki/Vulcans">Vulcans</a>, and other fascinating life forms.</p> -<h2>How Do I Get Started?</h2> -<p>Read <a href="https://github.com/spockframework/spock/wiki/10-Reasons-to-use-Spock">ten reasons</a> why Spock is for you, run your first spec in <a href="https://gwc-experiment.appspot.com/?gist=58f61cf36e112ff654041eeec8d11a98">Groovy Web Console</a>, fork the <a href="https://github.com/spockframework/spock-example">spock-example</a> project, learn how to write a specification, or dive into the <a href="https://docs.spockframework.org">reference documentation</a>.</p> -<h2>Install</h2> -<h3>with Gradle</h3> -<pre><span class="hljs-selector-tag">testImplementation</span> "<span class="hljs-selector-tag">org</span><span class="hljs-selector-class">.spockframework</span><span class="hljs-selector-pseudo">:spock-core</span><span class="hljs-selector-pseudo">:2.1-groovy-3.0"</span></pre><h3>with Maven:</h3> -<pre><span class="hljs-tag"><<span class="hljs-name">dependency</span>></span> - <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.spockframework<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span> - <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spock-core<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span> - <span class="hljs-tag"><<span class="hljs-name">version</span>></span>2.1-groovy-3.0<span class="hljs-tag"></<span class="hljs-name">version</span>></span> - <span class="hljs-tag"><<span class="hljs-name">scope</span>></span>test<span class="hljs-tag"></<span class="hljs-name">scope</span>></span> -<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></pre><h2>Where Are The Docs?</h2> -<ul> -<li>Reference Documentation: <a href="http://docs.spockframework.org">http://docs.spockframework.org</a></li> -<li>Javadoc: <a href="https://spockframework.org/spock/javadoc/current">https://spockframework.org/spock/javadoc/current</a></li> -</ul> -<h2>How Can I Get Involved?</h2> -<ul> -<li>Source Code: <a href="https://github.com/spockframework/spock">https://github.com/spockframework/spock</a></li> -<li>Issue Tracker: <a href="https://github.com/spockframework/spock/issues">https://github.com/spockframework/spock/issues</a></li> -<li>Discussion Chat: <a href="https://gitter.im/spockframework/spock">https://gitter.im/spockframework/spock</a></li> -</ul> -</div></article></div><footer><div style="box-sizing:border-box;max-width:1024px;margin-left:auto;margin-right:auto;margin-bottom:32px;padding-top:8px;padding-bottom:8px;padding-left:32px;padding-right:32px;"><div style="margin-left:-16px;margin-right:-16px;"><a href="https://github.com/spockframework/spock" class="Link" style="box-sizing:border-box;color:inherit;display:inline-block;font-size:14px;line-height:16px;padding-left:16px;padding-right:16px;padding-top:16px;padding-bottom:16px;font-weight:600;text-decoration:none;">GitHub</a><a href="https://github.com/spockframework/spock/issues" class="Link" style="box-sizing:border-box;color:inherit;display:inline-block;font-size:14px;line-height:16px;padding-left:16px;padding-right:16px;padding-top:16px;padding-bottom:16px;font-weight:600;text-decoration:none;">Issues</a><a href="https://gitter.im/spockframework/spock/" class="Link" style="box-sizing:border-box;color:inherit;display:inline-block;font-size:14px;line-height:16px;padding-left:16px;padding-right:16px;padding-top:16px;padding-bottom:16px;font-weight:600;text-decoration:none;">Chat</a><a href="http://docs.spockframework.org/" class="Link" style="box-sizing:border-box;color:inherit;display:inline-block;font-size:14px;line-height:16px;padding-left:16px;padding-right:16px;padding-top:16px;padding-bottom:16px;font-weight:600;text-decoration:none;">Documentation</a></div><div></div></div></footer></div><div style="font-family:-apple-system, sans-serif;font-size:12px;font-weight:600;text-align:right;padding:24px;color:#333;background-color:#eee;"><a href="http://compositor.io" style="color:inherit;text-decoration:none;">Built with Compositor.io</a></div></body></html> +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Spock Framework - the enterprise-ready specification framework</title> + <meta name="description" content="Spock is an expressive testing and specification framework for Java and Groovy applications. Write highly readable, maintainable BDD-style tests with powerful mocking."> + <meta name="keywords" content="Spock Framework, Groovy, Java, Kotlin, JVM, testing, specification, BDD, Behavior-Driven Development, unit testing, mocking, JUnit, JUnit 5"> + <meta name="author" content="Spock Framework Team"> + <link rel="canonical" href="https://spockframework.org/"> + <meta name="robots" content="index, follow"> + + <meta property="og:type" content="website"> + <meta property="og:url" content="https://spockframework.org/"> <meta property="og:title" content="Spock Framework - the enterprise-ready specification framework"> + <meta property="og:description" content="Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain."> + <meta property="og:image" content="spock-main-logo.svg"> + <meta property="twitter:card" content="summary"> + <meta property="twitter:url" content="https://spockframework.org/"> <meta property="twitter:title" content="Spock Framework - the enterprise-ready specification framework"> + <meta property="twitter:description" content="Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain."> + <meta property="twitter:image" content="spock-main-logo.svg"> + + <script src="https://cdn.tailwindcss.com"></script> + <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" + integrity="sha384-/rJKQnzOkEo+daG0jMjU1IwwY9unxt1NBw3Ef2fmOJ3PW/TfAg2KXVoWwMZQZtw9" + crossorigin="anonymous"> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> + <style> + /* Custom styles - Dark theme is now default */ + body { + font-family: 'Inter', sans-serif; + /* Dark mode defaults */ + background-color: #111827; /* Darker gray background */ + color: #d1d5db; /* Lighter gray text */ + transition: background-color 0.3s ease, color 0.3s ease; /* Smooth transition */ + } + + /* Spock primary color variable */ + :root { + --spock-blue: #1562ae; + --spock-blue-dark-text: #60a5fa; /* Lighter blue for text/links in dark */ + } + .spock-blue-bg { background-color: var(--spock-blue); } + /* Use the lighter blue for text elements in dark mode */ + .spock-blue-text { color: var(--spock-blue-dark-text); } + .spock-blue-border { border-color: var(--spock-blue-dark-text); } /* Use lighter blue for borders */ + + /* Style for code block */ + pre { + background-color: #2d3748; /* Dark background for code */ + color: #e2e8f0; /* Light text for code */ + padding: 1.5rem; + border-radius: 0.5rem; /* Rounded corners */ + overflow-x: auto; /* Allow horizontal scrolling */ + font-family: 'Courier New', Courier, monospace; + font-size: 0.9em; + line-height: 1.6; + } + /* Syntax highlighting colors */ + code .keyword { color: #9ae6b4; } /* Green */ + code .string { color: #fbd38d; } /* Orange */ + code .comment { color: #a0aec0; } /* Gray */ + code .class-name { color: #faf089; } /* Yellow */ + code .number { color: #fca5a5; } /* Red */ + + /* Style for inline code elements within regular text */ + .inline-code { + color: #cbd5e1; /* Slightly lighter gray for inline code */ + background-color: #374151; /* Slightly lighter dark background */ + padding: 0.1em 0.4em; + border-radius: 0.25rem; + font-size: 0.875em; /* Slightly smaller font size */ + font-family: 'Courier New', Courier, monospace; + } + + + /* Button Styling */ + .cta-button { + display: inline-block; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + font-weight: 600; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; + } + /* Primary Button */ + .cta-primary { + background-color: var(--spock-blue); /* Original blue for background */ + color: white; + } + .cta-primary:hover { + background-color: #115192; /* Darker blue on hover */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(21, 98, 174, 0.3); + } + + /* Secondary Button */ + .cta-secondary { + background-color: transparent; + color: var(--spock-blue-dark-text); /* Lighter blue text */ + border-color: var(--spock-blue-dark-text); /* Lighter blue border */ + } + /* Dark mode secondary button hover */ + .cta-secondary:hover { + background-color: rgba(59, 130, 246, 0.2); /* Lighter blue tint for dark bg */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(59, 130, 246, 0.1); + } + + /* Tertiary Button */ + .cta-tertiary { + background-color: #374151; /* Dark gray background */ + color: #d1d5db; /* Light gray text */ + } + .cta-tertiary:hover { + background-color: #4b5563; /* Slightly lighter dark gray on hover */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(255, 255, 255, 0.05); + } + + /* Simple underline animation for links */ + .hover-underline-animation { + display: inline-block; + position: relative; + color: var(--spock-blue-dark-text); /* Lighter blue for dark mode */ + transition: color 0.3s ease; + } + + .hover-underline-animation::after { + content: ''; + position: absolute; + width: 100%; + transform: scaleX(0); + height: 2px; + bottom: 0; + left: 0; + background-color: var(--spock-blue-dark-text); /* Lighter blue underline */ + transform-origin: bottom right; + transition: transform 0.25s ease-out, background-color 0.3s ease; + } + + .hover-underline-animation:hover::after { + transform: scaleX(1); + transform-origin: bottom left; + } + + /* Feature Card Styling */ + .feature-card { + background-color: #374151; /* Changed from #1f2937 for better contrast vs bg-gray-800 */ + padding: 1.5rem; /* p-6 */ + border-radius: 0.5rem; /* rounded-lg */ + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */ + transition: transform 0.3s ease, box-shadow 0.3s ease; + } + .feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* shadow-lg */ + } + + .feature-card svg { + height: 40px; + margin-bottom: 1rem; + fill: none; + stroke: var(--spock-blue); + stroke-width: 2; + } + + /* Additional Links Separator */ + .link-separator { + margin-left: 0.75rem; /* mx-3 */ + margin-right: 0.75rem; /* mx-3 */ + color: #4b5563; /* gray-600 */ + } + </style> +</head> +<body class="leading-normal tracking-normal"> + +<section class="pt-24 pb-16 md:pt-32 md:pb-24 bg-gray-800"> + <div class="container mx-auto px-6 text-center"> + <div class="mb-8"> + <img + src="spock-main-logo.svg" + alt="Spock Framework Logo" + class="h-64 w-auto mx-auto block logo-img"> + </div> + + <h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-4 spock-blue-text"> + Spock + </h1> + <p class="text-xl md:text-2xl text-gray-400 mb-8"> + the enterprise-ready specification framework + </p> + <p class="max-w-3xl mx-auto text-lg text-gray-300 mb-12"> + Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. + By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain. + </p> + </div> +</section> + +<section class="py-16 md:py-24"> + <div class="container mx-auto px-6 text-center"> + <h2 class="text-3xl md:text-4xl font-bold mb-8 text-gray-100" data-aos="fade-up">Ready to Improve Your Testing?</h2> + + <div class="flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4" data-aos="fade-up" data-aos-delay="200"> + <a href="https://groovyconsole.dev/?g=groovy_4_0&gist=437e9026ff86d2d709c2c56eb7e2eef1#g8qcDpYAQE" target="_blank" class="cta-button cta-primary"> + Try it online + </a> + <a href="https://docs.spockframework.org" target="_blank" class="cta-button cta-secondary"> + Read the Docs + </a> + <a href="https://github.com/spockframework/spock-example" target="_blank" class="cta-button cta-tertiary"> + Clone the Example Project + </a> + </div> + </div> + <div class="container mx-auto px-6 text-center spock-blue-text text-md additional-links flex flex-wrap justify-center items-center gap-y-2 pt-8" data-aos="fade-up" data-aos-delay="300"> + <a href="https://spockframework.org/spock/javadoc/current" class="mx-3 hover-underline-animation">JavaDoc</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock" class="mx-3 hover-underline-animation">Source Code</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock/issues" class="mx-3 hover-underline-animation">Issue Tracker</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock/discussions" class="mx-3 hover-underline-animation">Discussions</a> <span class="link-separator">|</span> + <a href="https://gitter.im/spockframework/spock" class="mx-3 hover-underline-animation">Chat</a> + </div> +</section> + + +<section class="py-16 md:py-24 bg-gray-800"> + <div class="container mx-auto px-6"> + <h2 class="text-3xl md:text-4xl font-bold text-center mb-16 text-gray-100" data-aos="fade-up"> + Why Choose Spock? + </h2> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> + <div class="feature-card" data-aos="fade-up" data-aos-delay="100"> + <svg viewBox="0 0 24 24"><rect x="4" y="4" width="16" height="16" rx="2"/></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Expressive Specifications</h3> + <p class="text-gray-300">Write tests that are easy to read and understand, even for non-programmers.</p> + </div> + <div class="feature-card" data-aos="fade-up" data-aos-delay="150"> + <svg viewBox="0 0 24 24"><path d="M3 17l6-6 4 4 8-8" /></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Powerful Mocking</h3> + <p class="text-gray-300">Create flexible and powerful mocks and stubs with built-in support.</p> + </div> + <div class="feature-card" data-aos="fade-up" data-aos-delay="200"> + <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">JUnit Platform</h3> + <p class="text-gray-300">Seamless integration with JUnit 5+ and build tools.</p> + </div> + <div class="feature-card" data-aos="fade-up" data-aos-delay="250"> + <svg viewBox="0 0 24 24"><path d="M3 3h18v6H3zM3 15h18v6H3z" /><path d="M9 9v6" /></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Data-Driven Testing</h3> + <p class="text-gray-300">Easily run the same test with different sets of data.</p> + </div> + <div class="feature-card" data-aos="fade-up" data-aos-delay="300"> + <svg viewBox="0 0 24 24"><polygon points="12 2 15 8 22 9 17 14 18 21 12 18 6 21 7 14 2 9 9 8 12 2" /></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Groovy DSL</h3> + <p class="text-gray-300">Leverage the power and flexibility of the Groovy language.</p> + </div> + <div class="feature-card" data-aos="fade-up" data-aos-delay="350"> + <svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" /><path d="M9 12l2 2 4-4" /></svg> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Built-in Matchers</h3> + <p class="text-gray-300">Use a rich set of matchers to verify expectations with clarity.</p> + </div> + </div> + </div> +</section> + +<section class="py-16 md:py-24"> + <div class="container mx-auto px-6"> + <h2 class="text-3xl md:text-4xl font-bold text-center mb-12 text-gray-100" data-aos="fade-up"> + See How Readable Tests Can Be + </h2> + <div class="max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="100"> + <pre><code class="language-groovy"><span class="comment">// CalculatorSpec.groovy</span> +<span class="keyword">import</span> spock.lang.Specification + +<span class="keyword">class</span> <span class="class-name">CalculatorSpec</span> <span class="keyword">extends</span> Specification { + + <span class="keyword">def</span> <span class="string">"Test calculate method: #a #operation #b = #expectedResult"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">expect:</span> <span class="comment">"The calculation should match the expected value"</span> + calculator.calculate(a, b, operation) == expectedResult + + <span class="keyword">where:</span> <span class="comment">"Define test data"</span> + a | b | operation || expectedResult + <span class="number">1</span> | <span class="number">2</span> | <span class="string">"+"</span> || <span class="number">3</span> + <span class="number">5</span> | <span class="number">3</span> | <span class="string">"-"</span> || <span class="number">2</span> + <span class="number">4</span> | <span class="number">2</span> | <span class="string">"*"</span> || <span class="number">8</span> + <span class="number">10</span> | <span class="number">2</span> | <span class="string">"/"</span> || <span class="number">5</span> + <span class="number">-1</span> | <span class="number">1</span> | <span class="string">"+"</span> || <span class="number">0</span> + <span class="number">1</span> | <span class="number">-1</span> | <span class="string">"-"</span> || <span class="number">2</span> + <span class="number">-2</span> | <span class="number">-2</span> | <span class="string">"*"</span> || <span class="number">4</span> + <span class="number">-4</span> | <span class="number">-2</span> | <span class="string">"/"</span> || <span class="number">2</span> + <span class="number">1</span> | <span class="number">1</span> | <span class="string">"+"</span> || <span class="number">42</span> <span class="comment">// A failing test case</span> + } + + <span class="keyword">def</span> <span class="string">"Test calculate method with division by zero"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">when:</span> <span class="comment">"Perform division by zero"</span> + calculator.calculate(<span class="number">10</span>, <span class="number">0</span>, <span class="string">"/"</span>) + + <span class="keyword">then:</span> <span class="comment">"An IllegalArgumentException is thrown"</span> + <span class="keyword">def</span> exception = thrown(<span class="class-name">IllegalArgumentException</span>) + + <span class="keyword">and:</span> <span class="comment">"The exception message is correct"</span> + exception.message == <span class="string">"Cannot divide by zero"</span> + } + + <span class="keyword">def</span> <span class="string">"Test calculate method with invalid operation"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">when:</span> <span class="comment">"Perform calculation with invalid operation"</span> + calculator.calculate(<span class="number">1</span>, <span class="number">2</span>, <span class="string">"**"</span>) + + <span class="keyword">then:</span> <span class="comment">"An IllegalArgumentException is thrown"</span> + <span class="keyword">def</span> exception = thrown(<span class="class-name">IllegalArgumentException</span>) + + <span class="keyword">and:</span> <span class="comment">"The exception message is correct"</span> + exception.message == <span class="string">"Invalid operation: **"</span> + } +} + + +<span class="comment">// Calculator.groovy</span> +<span class="keyword">class</span> <span class="class-name">Calculator</span> { +<span class="comment"> /** + * Performs arithmetic operations on two integers. + * + * <span class="annotation">@param</span> a The first integer. + * <span class="annotation">@param</span> b The second integer. + * <span class="annotation">@param</span> operation The operation to perform (+, -, *, /). + * <span class="annotation">@return</span> The result of the operation. + * <span class="annotation">@throws</span> IllegalArgumentException if the operation is invalid or division by zero is attempted. + */</span> + <span class="keyword">int</span> calculate(<span class="keyword">int</span> a, <span class="keyword">int</span> b, <span class="class-name">String</span> operation) { + <span class="keyword">switch</span> (operation) { + <span class="keyword">case</span> <span class="string">"+"</span>: <span class="keyword">return</span> a + b + <span class="keyword">case</span> <span class="string">"-"</span>: <span class="keyword">return</span> a - b + <span class="keyword">case</span> <span class="string">"*"</span>: <span class="keyword">return</span> a * b + <span class="keyword">case</span> <span class="string">"/"</span>: + <span class="keyword">if</span> (b == <span class="number">0</span>) { + <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class-name">IllegalArgumentException</span>(<span class="string">"Cannot divide by zero"</span>) + } + <span class="keyword">return</span> a / b + <span class="keyword">default</span>: + <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class-name">IllegalArgumentException</span>(<span class="string">"Invalid operation: "</span> + operation) + } + } + + <span class="class-name">String</span> toString() { + <span class="keyword">return</span> <span class="string">"Calc"</span> + } +} +</code></pre> + <p class="text-center text-gray-400 mt-6" data-aos="fade-up" data-aos-delay="200"> + Spock's clear <code class="inline-code">given:</code>, <code class="inline-code">when:</code>, <code class="inline-code">then:</code> blocks make understanding test logic intuitive. + </p> + <div class="mt-12" data-aos="fade-up" data-aos-delay="500"> + <h3 class="text-xl font-semibold text-center mb-4 text-gray-100">Example Test Output:</h3> + <pre>╷ +└─ Spock ✔ + └─ CalculatorSpec ✔ + ├─ Test calculate method: #a #operation #b = #expectedResult ✔ + │ ├─ Test calculate method: 1 + 2 = 3 ✔ + │ ├─ Test calculate method: 5 - 3 = 2 ✔ + │ ├─ Test calculate method: 4 * 2 = 8 ✔ + │ ├─ Test calculate method: 10 / 2 = 5 ✔ + │ ├─ Test calculate method: -1 + 1 = 0 ✔ + │ ├─ Test calculate method: 1 - -1 = 2 ✔ + │ ├─ Test calculate method: -2 * -2 = 4 ✔ + │ ├─ Test calculate method: -4 / -2 = 2 ✔ + │ └─ Test calculate method: 1 + 1 = 42 ✘ Condition not satisfied: + │ + │ calculator.calculate(a, b, operation) == expectedResult + │ | | | | | | | + │ Calc 2 1 1 + | 42 + │ false + ├─ Test calculate method with division by zero ✔ + └─ Test calculate method with invalid operation ✔</pre> + </div> + </div> + </div> + <div class="flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 mt-8" data-aos="fade-up" data-aos-delay="800"> + <a href="https://groovyconsole.dev/?g=groovy_4_0&gist=437e9026ff86d2d709c2c56eb7e2eef1#g8qcDpYAQE" target="_blank" class="cta-button cta-primary"> + Try it online + </a> + </div> +</section> + +<footer class="py-8 text-center text-gray-400 text-sm"> + <div class="container mx-auto px-6"> + © 2025 Spock Framework Team. All rights reserved. + </div> +</footer> + + +<script src="https://unpkg.com/aos@2.3.1/dist/aos.js" + integrity="sha384-wziAfh6b/qT+3LrqebF9WeK4+J5sehS6FA10J1t3a866kJ/fvU5UwofWnQyzLtwu" + crossorigin="anonymous"></script> +<script> + // Initialize AOS library + AOS.init({ + duration: 800, // Animation duration + once: true, // Whether animation should happen only once - while scrolling down + offset: 50, // Offset (in px) from the original trigger point + }); +</script> + +</body> +</html> diff --git a/spock-website/index.html b/spock-website/index.html new file mode 100644 index 0000000..d9028c3 --- /dev/null +++ b/spock-website/index.html @@ -0,0 +1,298 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Spock Framework - the enterprise-ready specification framework</title> + <meta name="description" content="Spock is an expressive testing and specification framework for Java and Groovy applications. Write highly readable, maintainable BDD-style tests with powerful mocking."> + <meta name="keywords" content="Spock Framework, Groovy, Java, Kotlin, JVM, testing, specification, BDD, Behavior-Driven Development, unit testing, mocking, JUnit, JUnit 5"> + <meta name="author" content="Spock Framework Team"> + <link rel="canonical" href="https://spockframework.org/"> + <meta name="robots" content="index, follow"> + + <meta property="og:type" content="website"> + <meta property="og:url" content="https://spockframework.org/"> <meta property="og:title" content="Spock Framework - the enterprise-ready specification framework"> + <meta property="og:description" content="Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain."> + <meta property="og:image" content="spock-main-logo.svg"> + <meta property="twitter:card" content="summary"> + <meta property="twitter:url" content="https://spockframework.org/"> <meta property="twitter:title" content="Spock Framework - the enterprise-ready specification framework"> + <meta property="twitter:description" content="Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain."> + <meta property="twitter:image" content="spock-main-logo.svg"> + + <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" + integrity="sha384-/rJKQnzOkEo+daG0jMjU1IwwY9unxt1NBw3Ef2fmOJ3PW/TfAg2KXVoWwMZQZtw9" + crossorigin="anonymous"> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> +</head> +<body class="leading-normal tracking-normal"> + +<section class="pt-24 pb-16 md:pt-32 md:pb-24 bg-gray-800"> + <div class="container mx-auto px-6 text-center"> + <div class="mb-8"> + <img + src="spock-main-logo.svg" + alt="Spock Framework Logo" + class="h-64 w-auto mx-auto block logo-img"> + </div> + + <h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-4 spock-blue-text"> + Spock + </h1> + <p class="text-xl md:text-2xl text-gray-400 mb-8"> + the enterprise-ready specification framework + </p> + <p class="max-w-3xl mx-auto text-lg text-gray-300 mb-12"> + Spock is a testing, specification, and mocking framework for JVM developers that emphasizes readability and clarity. + By blending BDD concepts and Groovy's concise syntax, Spock helps teams write tests that are easy to understand and enjoyable to maintain. + </p> + </div> +</section> + +<section class="py-16 md:py-24"> + <div class="container mx-auto px-6 text-center"> + <h2 class="text-3xl md:text-4xl font-bold mb-8 text-gray-100" data-aos="fade-up">Ready to Improve Your Testing?</h2> + + <div class="flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4" data-aos="fade-up" data-aos-delay="200"> + <a href="https://groovyconsole.dev/?g=groovy_4_0&gist=437e9026ff86d2d709c2c56eb7e2eef1#g8qcDpYAQE" target="_blank" class="cta-button cta-primary"> + <i class="fa-solid fa-laptop-code"></i> Try it online + </a> + <a href="https://docs.spockframework.org" target="_blank" class="cta-button cta-tertiary"> + <i class="fa-solid fa-book"></i> Read the Docs + </a> + <a href="https://github.com/spockframework/spock-example" target="_blank" class="cta-button cta-tertiary"> + <i class="fa-solid fa-code"></i> Clone the Example Project + </a> + </div> + </div> + <div class="container mx-auto px-6 text-center spock-blue-text text-md additional-links flex flex-wrap justify-center items-center gap-y-2 pt-8" data-aos="fade-up" data-aos-delay="300"> + <a href="https://spockframework.org/spock/javadoc/current" class="mx-3 hover-underline-animation"><i class="fa-brands fa-java"></i> JavaDoc</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock" class="mx-3 hover-underline-animation"><i class="fa-brands fa-github fa-lg"></i> Code & Issues</a> <span class="link-separator">|</span> + <a href="https://stackoverflow.com/questions/tagged/spock" class="mx-3 hover-underline-animation"><i class="fa-brands fa-stack-overflow"></i> Q&A</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock/discussions" class="mx-3 hover-underline-animation"><i class="fas fa-comment-dots"></i> Discussions</a> <span class="link-separator">|</span> + <a href="https://gitter.im/spockframework/spock" class="mx-3 hover-underline-animation"><i class="fas fa-comments"></i> Chat</a> + </div> + <div class="text-center mt-8 flex flex-wrap justify-center items-center" data-aos="fade-up" data-aos-delay="400"> + <a href="https://search.maven.org/search?q=g:org.spockframework" target="_blank"><img src="https://img.shields.io/maven-central/v/org.spockframework/spock-core?style=for-the-badge&label=Latest%20Version&labelColor=374151&color=1562ae" alt="Spock Latest Version"></a> + </div> +</section> + + +<section class="py-16 md:py-24 bg-gray-800"> + <div class="container mx-auto px-6"> + <h2 class="text-3xl md:text-4xl font-bold text-center mb-16 text-gray-100" data-aos="fade-up"> + Why Choose Spock? + </h2> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> + <div data-aos="fade-up" data-aos-delay="100"> + <div class="feature-card h-full"> + <div><i class="fas fa-receipt spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Expressive Specifications</h3> + <p class="text-gray-300">Write tests that are easy to read and understand, even for + non-programmers.</p> + </div> + </div> + <div data-aos="fade-up" data-aos-delay="200"> + <div class="feature-card h-full"> + <div><i class="fas fa-masks-theater spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Powerful Mocking</h3> + <p class="text-gray-300">Create flexible and powerful mocks and stubs with built-in support.</p> + </div> + </div> + <div data-aos="fade-up" data-aos-delay="300"> + <div class="feature-card h-full"> + <div><i class="fas fa-vial-circle-check spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">JUnit Platform</h3> + <p class="text-gray-300">Seamless integration with JUnit 5+ and build tools.</p> + </div> + </div> + <div data-aos="fade-up" data-aos-delay="400"> + <div class="feature-card h-full"> + <div><i class="fas fa-table-cells spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Data-Driven Testing</h3> + <p class="text-gray-300">Easily run the same test with different sets of data.</p> + </div> + </div> + <div data-aos="fade-up" data-aos-delay="500"> + <div class="feature-card h-full"> + <div><i class="fas fa-star spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Groovy DSL</h3> + <p class="text-gray-300">Leverage the power and flexibility of the Groovy language.</p> + </div> + </div> + <div data-aos="fade-up" data-aos-delay="600"> + <div class="feature-card h-full"> + <div><i class="fas fa-circle-check spock-blue-text"></i></div> + <h3 class="text-xl font-semibold text-gray-100 mb-2">Built-in Matchers</h3> + <p class="text-gray-300">Use a rich set of matchers to verify expectations with clarity.</p> + </div> + </div> + </div> + </div> +</section> + +<section class="py-16 md:py-24"> + <div class="container mx-auto px-6"> + <h2 class="text-3xl md:text-4xl font-bold text-center mb-12 text-gray-100" data-aos="fade-up"> + See How Readable Tests Can Be + </h2> + <div class="max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="100"> + <pre><code class="language-groovy"><span class="comment">// CalculatorSpec.groovy</span> +<span class="keyword">import</span> spock.lang.Specification + +<span class="keyword">class</span> <span class="class-name">CalculatorSpec</span> <span class="keyword">extends</span> Specification { + + <span class="keyword">def</span> <span class="string">"Test calculate method: #a #operation #b = #expectedResult"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">expect:</span> <span class="comment">"The calculation should match the expected value"</span> + calculator.calculate(a, b, operation) == expectedResult + + <span class="keyword">where:</span> <span class="comment">"Define test data"</span> + a | b | operation || expectedResult + <span class="number">1</span> | <span class="number">2</span> | <span class="string">"+"</span> || <span class="number">3</span> + <span class="number">5</span> | <span class="number">3</span> | <span class="string">"-"</span> || <span class="number">2</span> + <span class="number">4</span> | <span class="number">2</span> | <span class="string">"*"</span> || <span class="number">8</span> + <span class="number">10</span> | <span class="number">2</span> | <span class="string">"/"</span> || <span class="number">5</span> + <span class="number">-1</span> | <span class="number">1</span> | <span class="string">"+"</span> || <span class="number">0</span> + <span class="number">1</span> | <span class="number">-1</span> | <span class="string">"-"</span> || <span class="number">2</span> + <span class="number">-2</span> | <span class="number">-2</span> | <span class="string">"*"</span> || <span class="number">4</span> + <span class="number">-4</span> | <span class="number">-2</span> | <span class="string">"/"</span> || <span class="number">2</span> + <span class="number">1</span> | <span class="number">1</span> | <span class="string">"+"</span> || <span class="number">42</span> <span class="comment">// A failing test case</span> + } + + <span class="keyword">def</span> <span class="string">"Test calculate method with division by zero"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">when:</span> <span class="comment">"Perform division by zero"</span> + calculator.calculate(<span class="number">10</span>, <span class="number">0</span>, <span class="string">"/"</span>) + + <span class="keyword">then:</span> <span class="comment">"An IllegalArgumentException is thrown"</span> + <span class="keyword">def</span> exception = thrown(<span class="class-name">IllegalArgumentException</span>) + + <span class="keyword">and:</span> <span class="comment">"The exception message is correct"</span> + exception.message == <span class="string">"Cannot divide by zero"</span> + } + + <span class="keyword">def</span> <span class="string">"Test calculate method with invalid operation"</span>() { + <span class="keyword">given:</span> <span class="comment">"A calculator instance"</span> + <span class="keyword">def</span> calculator = <span class="keyword">new</span> <span class="class-name">Calculator</span>() + + <span class="keyword">when:</span> <span class="comment">"Perform calculation with invalid operation"</span> + calculator.calculate(<span class="number">1</span>, <span class="number">2</span>, <span class="string">"**"</span>) + + <span class="keyword">then:</span> <span class="comment">"An IllegalArgumentException is thrown"</span> + <span class="keyword">def</span> exception = thrown(<span class="class-name">IllegalArgumentException</span>) + + <span class="keyword">and:</span> <span class="comment">"The exception message is correct"</span> + exception.message == <span class="string">"Invalid operation: **"</span> + } +} + + +<span class="comment">// Calculator.groovy</span> +<span class="keyword">class</span> <span class="class-name">Calculator</span> { +<span class="comment"> /** + * Performs arithmetic operations on two integers. + * + * <span class="annotation">@param</span> a The first integer. + * <span class="annotation">@param</span> b The second integer. + * <span class="annotation">@param</span> operation The operation to perform (+, -, *, /). + * <span class="annotation">@return</span> The result of the operation. + * <span class="annotation">@throws</span> IllegalArgumentException if the operation is invalid or division by zero is attempted. + */</span> + <span class="keyword">int</span> calculate(<span class="keyword">int</span> a, <span class="keyword">int</span> b, <span class="class-name">String</span> operation) { + <span class="keyword">switch</span> (operation) { + <span class="keyword">case</span> <span class="string">"+"</span>: <span class="keyword">return</span> a + b + <span class="keyword">case</span> <span class="string">"-"</span>: <span class="keyword">return</span> a - b + <span class="keyword">case</span> <span class="string">"*"</span>: <span class="keyword">return</span> a * b + <span class="keyword">case</span> <span class="string">"/"</span>: + <span class="keyword">if</span> (b == <span class="number">0</span>) { + <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class-name">IllegalArgumentException</span>(<span class="string">"Cannot divide by zero"</span>) + } + <span class="keyword">return</span> a / b + <span class="keyword">default</span>: + <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class-name">IllegalArgumentException</span>(<span class="string">"Invalid operation: "</span> + operation) + } + } + + <span class="class-name">String</span> toString() { + <span class="keyword">return</span> <span class="string">"Calc"</span> + } +} +</code></pre> + <p class="text-center text-gray-400 mt-6" data-aos="fade-up" data-aos-delay="200"> + Spock's clear <code class="inline-code">given:</code>, <code class="inline-code">when:</code>, <code class="inline-code">then:</code> blocks make understanding test logic intuitive. + </p> + <div class="mt-12" data-aos="fade-up" data-aos-delay="500"> + <h3 class="text-xl font-semibold text-center mb-4 text-gray-100">Example Test Output:</h3> + <pre>╷ +└─ Spock ✔ + └─ CalculatorSpec ✔ + ├─ Test calculate method: #a #operation #b = #expectedResult ✔ + │ ├─ Test calculate method: 1 + 2 = 3 ✔ + │ ├─ Test calculate method: 5 - 3 = 2 ✔ + │ ├─ Test calculate method: 4 * 2 = 8 ✔ + │ ├─ Test calculate method: 10 / 2 = 5 ✔ + │ ├─ Test calculate method: -1 + 1 = 0 ✔ + │ ├─ Test calculate method: 1 - -1 = 2 ✔ + │ ├─ Test calculate method: -2 * -2 = 4 ✔ + │ ├─ Test calculate method: -4 / -2 = 2 ✔ + │ └─ Test calculate method: 1 + 1 = 42 ✘ Condition not satisfied: + │ + │ calculator.calculate(a, b, operation) == expectedResult + │ | | | | | | | + │ Calc 2 1 1 + | 42 + │ false + ├─ Test calculate method with division by zero ✔ + └─ Test calculate method with invalid operation ✔</pre> + </div> + </div> + </div> + <div class="flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 mt-8" data-aos="fade-up" data-aos-delay="800"> + <a href="https://groovyconsole.dev/?g=groovy_4_0&gist=437e9026ff86d2d709c2c56eb7e2eef1#g8qcDpYAQE" target="_blank" class="cta-button cta-primary"> + <i class="fa-solid fa-laptop-code"></i> Try it online + </a> + </div> +</section> + +<section class="py-16 bg-gray-800"> + <div class="container mx-auto px-6"> + <h3 class="text-3xl md:text-4xl font-bold text-center text-gray-100" data-aos="fade-up"> + Follow Us on + </h3> + <div class="container mx-auto px-6 text-center spock-blue-text text-md additional-links flex flex-wrap justify-center items-center gap-y-2 pt-8" data-aos="fade-up" data-aos-delay="100"> + <a href="https://fosstodon.org/@spockframework" class="mx-3 hover-underline-animation"><i class="fa-brands fa-mastodon"></i> @spockframework</a> <span class="link-separator">|</span> + <a href="https://bsky.app/profile/spockframework.org" class="mx-3 hover-underline-animation"><i class="fa-brands fa-bluesky"></i> spockframework.org</a> <span class="link-separator">|</span> + <a href="https://twitter.com/SpockFramework" class="mx-3 hover-underline-animation"><i class="fa-brands fa-x-twitter"></i> @spockframework</a> <span class="link-separator">|</span> + <a href="https://github.com/spockframework/spock" class="mx-3 hover-underline-animation"><i class="fa-brands fa-github fa-lg"></i> spockframework/spock</a> + </div> + </div> +</section> + +<footer class="py-8 text-center text-gray-400 text-sm"> + <div class="container mx-auto px-6"> + © 2025 Spock Framework Team. All rights reserved. + </div> +</footer> + + +<script src="https://unpkg.com/aos@2.3.1/dist/aos.js" + integrity="sha384-wziAfh6b/qT+3LrqebF9WeK4+J5sehS6FA10J1t3a866kJ/fvU5UwofWnQyzLtwu" + crossorigin="anonymous"></script> +<script> + // Initialize AOS library + AOS.init({ + duration: 800, // Animation duration + once: true, // Whether animation should happen only once - while scrolling down + offset: 50, // Offset (in px) from the original trigger point + disable: new URLSearchParams(window.location.search).get('disableaos') !== null, + }); +</script> + +<script type="module" src="/src/main.ts"></script> +</body> +</html> diff --git a/spock-website/package-lock.json b/spock-website/package-lock.json new file mode 100644 index 0000000..dbd83ab --- /dev/null +++ b/spock-website/package-lock.json @@ -0,0 +1,1616 @@ +{ + "name": "spock-website", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "spock-website", + "version": "0.0.0", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@tailwindcss/vite": "^4.1.4", + "tailwindcss": "^4.1.4" + }, + "devDependencies": { + "@playwright/test": "^1.52.0", + "typescript": "~5.7.2", + "vite": "^6.3.1" + } + }, + "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/@fortawesome/fontawesome-common-types": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz", + "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz", + "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==", + "license": "MIT", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz", + "integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz", + "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.7.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@playwright/test": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.52.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "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/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/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_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": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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/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/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/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": { + "detect-libc": "^2.0.3" + }, + "engines": { + "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/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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/nanoid": { + "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" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "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": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/playwright": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.52.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "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/source-map-js": { + "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/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/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "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": ">=14.17" + } + }, + "node_modules/vite": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz", + "integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.3", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.12" + }, + "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 + } + } + } + } +} diff --git a/spock-website/package.json b/spock-website/package.json new file mode 100644 index 0000000..59ddae1 --- /dev/null +++ b/spock-website/package.json @@ -0,0 +1,23 @@ +{ + "name": "spock-website", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@playwright/test": "^1.52.0", + "typescript": "~5.7.2", + "vite": "^6.3.1" + }, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@tailwindcss/vite": "^4.1.4", + "tailwindcss": "^4.1.4" + } +} diff --git a/spock-website/playwright.config.ts b/spock-website/playwright.config.ts new file mode 100644 index 0000000..dabb68f --- /dev/null +++ b/spock-website/playwright.config.ts @@ -0,0 +1,32 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + reporter: process.env.CI ? [['github'], ['html']] : [['html'], ['list']], + // Configure projects for major browsers. + projects: [ + { + name: 'chromium', + use: devices['Desktop Chrome'], + }, + { + name: 'firefox', + use: devices['Desktop Firefox'], + }, + ], + // Single template for all assertions + testDir: 'tests', + snapshotPathTemplate: '{testDir}/__screenshots__{/projectName}/{testFilePath}/{arg}{ext}', + // Run local dev server before starting the tests. + use: { + // Base URL to use in actions like `await page.goto('/')`. + baseURL: 'http://localhost:5173', + + // Collect trace when retrying the failed test. + trace: 'on-first-retry', + }, + webServer: { + command: 'npm run dev', + url: 'http://localhost:5173', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/spock-website/public/spock-main-logo.svg b/spock-website/public/spock-main-logo.svg new file mode 100644 index 0000000..5e732d1 --- /dev/null +++ b/spock-website/public/spock-main-logo.svg @@ -0,0 +1 @@ +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 552.35 623.05"><defs><style>.cls-1{fill:#1562ae;}.cls-2{fill:none;stroke:#050606;stroke-miterlimit:10;stroke-width:23px;}</style></defs><rect class="cls-1" width="552.35" height="623.05" rx="196.17"/><path class="cls-2" d="M478.05,270.53,538,187.62l-14.6,72.55-1.46,90.41a39.67,39.67,0,0,1-15.87,26.49l-28,23.67V437c0,83.29-68.15,151.43-151.44,151.43S175.2,520.3,175.2,437h92.28a71.68,71.68,0,0,0,12.82,26.61c3.83,4.94,18.8,22.87,43.66,26.5,35.79,5.24,61-23.73,63.34-26.5,27.46-32.62,13.86-74.39,12.84-77.35-10-29.09-66.16-58.1-73.51-62.86-11.47-7.74-69-43.16-76.18-64-1-3-14.62-44.73,12.84-77.35,2.34-2.77,27.55-31.74,63.34-26.5,24.86,3.63,39.83,21.56,43.66,26.5A67.5,67.5,0,0,1,384,212.25l.34,1.54h93.78c0-83.29-68.15-151.44-151.44-151.44S175.2,130.49,175.2,213.78V273.5l-3.09-4.27-60-82.91,14.6,72.55,1.46,90.41a39.67,39.67,0,0,0,15.87,26.49l31.93,27" transform="translate(-48.91 -13.87)"/></svg> \ No newline at end of file diff --git a/spock-website/src/icons.ts b/spock-website/src/icons.ts new file mode 100644 index 0000000..b329997 --- /dev/null +++ b/spock-website/src/icons.ts @@ -0,0 +1,9 @@ +import { library, dom } from '@fortawesome/fontawesome-svg-core'; +import { faBook, faCode, faLaptopCode, faComments, faCommentDots, faReceipt, faMasksTheater, faVialCircleCheck, faTableCells, faStar, faCircleCheck} from '@fortawesome/free-solid-svg-icons'; +import { faGithub, faStackOverflow, faJava, faXTwitter, faMastodon, faBluesky } from '@fortawesome/free-brands-svg-icons'; + +// Add icons to the library +library.add(faGithub, faStackOverflow, faJava, faXTwitter, faMastodon, faBluesky, faBook, faCode, faLaptopCode, faComments, faCommentDots, faReceipt, faMasksTheater, faVialCircleCheck, faTableCells, faStar, faCircleCheck); + +// Watch for <i> tags and replace with SVG +dom.watch(); diff --git a/spock-website/src/main.ts b/spock-website/src/main.ts new file mode 100644 index 0000000..3fa6072 --- /dev/null +++ b/spock-website/src/main.ts @@ -0,0 +1,2 @@ +import './style.css' +import './icons' diff --git a/spock-website/src/style.css b/spock-website/src/style.css new file mode 100644 index 0000000..f55d223 --- /dev/null +++ b/spock-website/src/style.css @@ -0,0 +1,148 @@ +@import "tailwindcss"; + +/* Custom styles - Dark theme is now default */ +body { + font-family: 'Inter', sans-serif; + /* Dark mode defaults */ + background-color: #111827; /* Darker gray background */ + color: #d1d5db; /* Lighter gray text */ + transition: background-color 0.3s ease, color 0.3s ease; /* Smooth transition */ +} + +/* Spock primary color variable */ +:root { + --spock-blue: #1562ae; + --spock-blue-dark-text: #60a5fa; /* Lighter blue for text/links in dark */ +} +.spock-blue-bg { background-color: var(--spock-blue); } +/* Use the lighter blue for text elements in dark mode */ +.spock-blue-text { color: var(--spock-blue-dark-text); } +.spock-blue-border { border-color: var(--spock-blue-dark-text); } /* Use lighter blue for borders */ + +/* Style for code block */ +pre { + background-color: #2d3748; /* Dark background for code */ + color: #e2e8f0; /* Light text for code */ + padding: 1.5rem; + border-radius: 0.5rem; /* Rounded corners */ + overflow-x: auto; /* Allow horizontal scrolling */ + font-family: 'Courier New', Courier, monospace; + font-size: 0.9em; + line-height: 1.6; +} +/* Syntax highlighting colors */ +code .keyword { color: #9ae6b4; } /* Green */ +code .string { color: #fbd38d; } /* Orange */ +code .comment { color: #a0aec0; } /* Gray */ +code .class-name { color: #faf089; } /* Yellow */ +code .number { color: #fca5a5; } /* Red */ + +/* Style for inline code elements within regular text */ +.inline-code { + color: #cbd5e1; /* Slightly lighter gray for inline code */ + background-color: #374151; /* Slightly lighter dark background */ + padding: 0.1em 0.4em; + border-radius: 0.25rem; + font-size: 0.875em; /* Slightly smaller font size */ + font-family: 'Courier New', Courier, monospace; +} + + +/* Button Styling */ +.cta-button { + display: inline-block; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + font-weight: 600; + text-align: center; + transition: all 0.3s ease; + border: 2px solid transparent; +} +/* Primary Button */ +.cta-primary { + background-color: var(--spock-blue); /* Original blue for background */ + color: white; +} +.cta-primary:hover { + background-color: #115192; /* Darker blue on hover */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(21, 98, 174, 0.3); +} + +/* Secondary Button */ +.cta-secondary { + background-color: transparent; + color: var(--spock-blue-dark-text); /* Lighter blue text */ + border-color: var(--spock-blue-dark-text); /* Lighter blue border */ +} +/* Dark mode secondary button hover */ +.cta-secondary:hover { + background-color: rgba(59, 130, 246, 0.2); /* Lighter blue tint for dark bg */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(59, 130, 246, 0.1); +} + +/* Tertiary Button */ +.cta-tertiary { + background-color: #374151; /* Dark gray background */ + color: #d1d5db; /* Light gray text */ +} +.cta-tertiary:hover { + background-color: #4b5563; /* Slightly lighter dark gray on hover */ + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(255, 255, 255, 0.05); +} + +/* Simple underline animation for links */ +.hover-underline-animation { + display: inline-block; + position: relative; + color: var(--spock-blue-dark-text); /* Lighter blue for dark mode */ + transition: color 0.3s ease; +} + +.hover-underline-animation::after { + content: ''; + position: absolute; + width: 100%; + transform: scaleX(0); + height: 2px; + bottom: 0; + left: 0; + background-color: var(--spock-blue-dark-text); /* Lighter blue underline */ + transform-origin: bottom right; + transition: transform 0.25s ease-out, background-color 0.3s ease; +} + +.hover-underline-animation:hover::after { + transform: scaleX(1); + transform-origin: bottom left; +} + +/* Feature Card Styling */ +.feature-card { + background-color: #374151; /* Changed from #1f2937 for better contrast vs bg-gray-800 */ + padding: 1.5rem; /* p-6 */ + border-radius: 0.5rem; /* rounded-lg */ + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */ + transition: transform 0.3s ease, box-shadow 0.3s ease; +} +.feature-card:hover { + transform: translateY(-8px); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* shadow-lg */ +} + +.feature-card svg { + height: 40px; + margin-bottom: 1rem; + fill: none; + stroke: var(--spock-blue); + stroke-width: 2; +} + +/* Additional Links Separator */ +.link-separator { + margin-left: 0.75rem; /* mx-3 */ + margin-right: 0.75rem; /* mx-3 */ + color: #4b5563; /* gray-600 */ +} diff --git a/spock-website/src/vite-env.d.ts b/spock-website/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/spock-website/src/vite-env.d.ts @@ -0,0 +1 @@ +/// <reference types="vite/client" /> diff --git a/spock-website/tests/visual.spec.ts b/spock-website/tests/visual.spec.ts new file mode 100644 index 0000000..9e023f6 --- /dev/null +++ b/spock-website/tests/visual.spec.ts @@ -0,0 +1,6 @@ +import { test, expect } from '@playwright/test'; + +test('visual snapshot', async ({ page }) => { + await page.goto('/?disableaos'); + await expect(page).toHaveScreenshot('index.png', { fullPage: true }); +}); diff --git a/spock-website/tsconfig.json b/spock-website/tsconfig.json new file mode 100644 index 0000000..a4883f2 --- /dev/null +++ b/spock-website/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "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": ["src"] +} diff --git a/spock-website/tsconfig.test.json b/spock-website/tsconfig.test.json new file mode 100644 index 0000000..fcc10ca --- /dev/null +++ b/spock-website/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": [ + "tests/**/*.spec.ts", + ], +} diff --git a/spock-website/vite.config.ts b/spock-website/vite.config.ts new file mode 100644 index 0000000..a326629 --- /dev/null +++ b/spock-website/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + base: '/', + plugins: [ + tailwindcss(), + ], +})