Add browser-interactive-testing skill and fix Biome/audit config
Integrate the rodney/showboat browser automation skill for headless Chrome screenshots and testing. Exclude .rodney and .agent-tests from Biome file scanning. Add picomatch override to resolve high-severity ReDoS vulnerability in knip/jscpd transitive deps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
206
.claude/skills/browser-interactive-testing/SKILL.md
Normal file
206
.claude/skills/browser-interactive-testing/SKILL.md
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
---
|
||||||
|
name: browser-interactive-testing
|
||||||
|
description: >
|
||||||
|
This skill should be used when the user asks to "test a web page",
|
||||||
|
"take a screenshot of a site", "automate browser interaction",
|
||||||
|
"create a test report", "verify a page works", or mentions
|
||||||
|
rodney, showboat, headless Chrome testing, or browser automation.
|
||||||
|
version: 0.1.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# Browser Interactive Testing
|
||||||
|
|
||||||
|
Test web pages interactively using **rodney** (headless Chrome automation) and document results with **showboat** (executable demo reports).
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Ensure `uv` is installed. If missing, instruct the user to run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Do NOT install rodney or showboat globally. Run them via `uvx`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney <command>
|
||||||
|
uvx showboat <command>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rodney Quick Reference
|
||||||
|
|
||||||
|
### Start a browser session
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney start # Launch headless Chrome
|
||||||
|
uvx rodney start --show # Launch visible browser (for debugging)
|
||||||
|
uvx rodney connect host:port # Connect to existing Chrome with remote debugging
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `--local` on all commands to scope the session to the current directory.
|
||||||
|
|
||||||
|
### Navigate and inspect
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney open "https://example.com"
|
||||||
|
uvx rodney waitload
|
||||||
|
uvx rodney title
|
||||||
|
uvx rodney url
|
||||||
|
uvx rodney text "h1"
|
||||||
|
uvx rodney html "#content"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interact with elements
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney click "#submit-btn"
|
||||||
|
uvx rodney input "#email" "user@example.com"
|
||||||
|
uvx rodney select "#country" "US"
|
||||||
|
uvx rodney js "document.querySelector('#app').dataset.ready"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Assert and verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney assert "document.title" "My App" -m "Title must match"
|
||||||
|
uvx rodney exists ".error-banner"
|
||||||
|
uvx rodney visible "#loading-spinner"
|
||||||
|
uvx rodney count ".list-item"
|
||||||
|
```
|
||||||
|
|
||||||
|
Exit code `0` = pass, `1` = fail, `2` = error.
|
||||||
|
|
||||||
|
### Screenshots and cleanup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx rodney screenshot -w 1280 -h 720 page.png
|
||||||
|
uvx rodney screenshot-el "#chart" chart.png
|
||||||
|
uvx rodney stop
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `uvx rodney --help` for the full command list, including tab management, navigation, waiting, accessibility tree inspection, and PDF export.
|
||||||
|
|
||||||
|
## Showboat Quick Reference
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvx showboat init report.md "Test Report Title"
|
||||||
|
uvx showboat note report.md "Description of what we are testing."
|
||||||
|
uvx showboat exec report.md bash "uvx rodney title --local"
|
||||||
|
uvx showboat image report.md ''
|
||||||
|
uvx showboat pop report.md # Remove last entry (fix mistakes)
|
||||||
|
uvx showboat verify report.md # Re-run all code blocks and diff
|
||||||
|
uvx showboat extract report.md # Print commands that recreate the document
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `uvx showboat --help` for details on `--workdir`, `--output`, `--filename`, and stdin piping.
|
||||||
|
|
||||||
|
## Output Directory
|
||||||
|
|
||||||
|
Save all reports under `.agent-tests/` in the project root:
|
||||||
|
|
||||||
|
```
|
||||||
|
.agent-tests/
|
||||||
|
└── YYYY-MM-DD-<slug>/
|
||||||
|
├── report.md
|
||||||
|
└── screenshots/
|
||||||
|
```
|
||||||
|
|
||||||
|
Derive the slug from the test subject (e.g., `login-flow`, `homepage-layout`). Keep it lowercase, hyphen-separated, max ~30 chars. If a directory with the same date and slug already exists, append a numeric suffix (e.g., `tetris-game-2`) or choose a more specific slug (e.g., `tetris-controls` instead of reusing `tetris-game`).
|
||||||
|
|
||||||
|
### Setup Script
|
||||||
|
|
||||||
|
Run the bundled `scripts/setup.py` to create the directory, init the report, start the browser, and capture `DIR` in one step. Replace `<SKILL_DIR>` with the actual path to the directory containing this skill's files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DIR=$(python3 <SKILL_DIR>/scripts/setup.py "<slug>" "<Report Title>")
|
||||||
|
```
|
||||||
|
|
||||||
|
This single command:
|
||||||
|
1. Creates `.agent-tests/YYYY-MM-DD-<slug>/screenshots/`
|
||||||
|
2. Adds `.rodney/` to `.gitignore` (if `.gitignore` exists)
|
||||||
|
3. Runs `showboat init` for the report
|
||||||
|
4. Starts a browser (connects to existing, launches system Chrome/Chromium, or falls back to rodney's built-in launcher)
|
||||||
|
5. Prints the directory path to stdout (all status messages go to stderr)
|
||||||
|
|
||||||
|
After setup, `$DIR` is ready for use with all subsequent commands.
|
||||||
|
|
||||||
|
**Important:** The `--local` flag stores session data in `.rodney/` relative to the current working directory. Do NOT `cd` to a different directory during the session, or rodney will lose the connection. Use absolute paths for file arguments instead.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. **Setup** — Run the setup script to create the dir, init the report, start the browser, and set `$DIR`
|
||||||
|
2. **Describe the test** — `uvx showboat note "$DIR/report.md" "Testing [subject] for [goals]."` so the report has context up front
|
||||||
|
3. **Open page** — `uvx showboat exec "$DIR/report.md" bash "uvx rodney open --local 'URL' && uvx rodney waitload --local"`
|
||||||
|
4. **Add a note** before each test group — Use a heading followed by a short explanation of what the tests in this section verify and why it matters. Use unique section titles; avoid duplicating headings within the same report.
|
||||||
|
```bash
|
||||||
|
uvx showboat note "$DIR/report.md" "## Keyboard Controls"
|
||||||
|
uvx showboat note "$DIR/report.md" "Verify arrow keys move and rotate the active piece, and that soft/hard drop work correctly."
|
||||||
|
```
|
||||||
|
5. **Run assertions** — Before each assertion, add a short `showboat note` explaining what it checks. Then wrap the `rodney assert` / `rodney js` call in `showboat exec`:
|
||||||
|
```bash
|
||||||
|
uvx showboat note "$DIR/report.md" "The left arrow key should move the piece one cell to the left."
|
||||||
|
uvx showboat exec "$DIR/report.md" bash "uvx rodney assert --local '...' '...' -m 'Piece moved left'"
|
||||||
|
```
|
||||||
|
6. **Capture screenshots** — Take the screenshot with `rodney screenshot`, then embed with `showboat image`. **Important:** `showboat image` resolves image paths relative to the current working directory, NOT relative to the report file. Always use absolute paths (`$DIR/screenshots/...`) in the markdown image reference to avoid "image file not found" errors:
|
||||||
|
```bash
|
||||||
|
uvx rodney screenshot --local -w 1280 -h 720 "$DIR/screenshots/01-initial-load.png"
|
||||||
|
uvx showboat image "$DIR/report.md" ""
|
||||||
|
```
|
||||||
|
Number screenshots sequentially (`01-`, `02-`, ...) and use descriptive filenames.
|
||||||
|
7. **Pop on failure** — If a command fails, run `showboat pop` then retry
|
||||||
|
8. **Stop browser** — `uvx rodney stop --local`
|
||||||
|
9. **Write summary** — Add a final `showboat note` with a summary section listing all pass/fail results and any bugs found. Every report must end with a summary.
|
||||||
|
10. **Verify report** — `uvx showboat verify "$DIR/report.md"`
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
- Use `uvx rodney waitload` or `uvx rodney wait <selector>` before interacting with page content.
|
||||||
|
- Run `uvx showboat pop` immediately after a failed `exec` to keep the report clean.
|
||||||
|
- Prefer `rodney assert` for checks — clear exit codes and self-documenting output.
|
||||||
|
- Use `rodney js` only for complex checks or state manipulation that `assert` cannot express.
|
||||||
|
- Take screenshots at key stages (initial load, after interaction, error states) for visual evidence.
|
||||||
|
- Add a `showboat note` before each logical group of tests with a heading and a short explanation of what the section tests. Use unique heading titles — duplicate headings make the report confusing.
|
||||||
|
- Always end reports with a summary `showboat note` listing pass/fail results and any bugs found. This is required, not optional.
|
||||||
|
|
||||||
|
## Quoting Rules for `rodney js`
|
||||||
|
|
||||||
|
`rodney js` evaluates a single JS **expression** (not statements). Nested shell quoting with `showboat exec` causes most errors. Follow these rules strictly:
|
||||||
|
|
||||||
|
1. **Wrap multi-statement JS in an IIFE** — bare `const`, `let`, `for` fail at top level:
|
||||||
|
```bash
|
||||||
|
# WRONG
|
||||||
|
uvx rodney js --local 'const x = 1; x + 2'
|
||||||
|
# CORRECT
|
||||||
|
uvx rodney js --local '(function(){ var x = 1; return x + 2; })()'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use `var` instead of `const`/`let`** inside IIFEs to avoid strict-mode eval scoping issues.
|
||||||
|
|
||||||
|
3. **Direct `rodney js` calls** — use single quotes for the outer shell, double quotes inside JS:
|
||||||
|
```bash
|
||||||
|
uvx rodney js --local '(function(){ var el = document.querySelector("#app"); return el.textContent; })()'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Inside `showboat exec`** — use a heredoc with a **quoted delimiter** (`<<'JSEOF'`) to prevent all shell expansion (`$`, backticks, etc.):
|
||||||
|
```bash
|
||||||
|
uvx showboat exec "$DIR/report.md" bash "$(cat <<'JSEOF'
|
||||||
|
uvx rodney js --local '
|
||||||
|
(function(){
|
||||||
|
var x = score;
|
||||||
|
hardDrop();
|
||||||
|
return "before:" + x + ",after:" + score;
|
||||||
|
})()
|
||||||
|
'
|
||||||
|
JSEOF
|
||||||
|
)"
|
||||||
|
```
|
||||||
|
For simple one-liners, single quotes inside the double-quoted bash arg also work:
|
||||||
|
```bash
|
||||||
|
uvx showboat exec "$DIR/report.md" bash "uvx rodney js --local '(function(){ return String(score); })()'"
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Avoid without heredoc**: backticks, `$` signs, unescaped double quotes. The heredoc pattern avoids all of these.
|
||||||
|
|
||||||
|
6. **Prefer `rodney assert` over `rodney js`** when possible — separate arguments avoid quoting entirely.
|
||||||
|
|
||||||
|
7. **Pop after syntax errors** — always `showboat pop` before retrying to keep the report clean.
|
||||||
160
.claude/skills/browser-interactive-testing/scripts/setup.py
Normal file
160
.claude/skills/browser-interactive-testing/scripts/setup.py
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Set up a browser-interactive-testing session.
|
||||||
|
|
||||||
|
Creates the output directory, inits the showboat report, starts a browser,
|
||||||
|
and prints the DIR path. Automatically detects whether rodney can launch
|
||||||
|
its own Chromium or falls back to a system-installed browser.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
REMOTE_DEBUG_PORT = 9222
|
||||||
|
|
||||||
|
|
||||||
|
def find_system_browser():
|
||||||
|
"""Return the path to a system Chrome/Chromium binary, or None."""
|
||||||
|
for name in ["chromium", "chromium-browser", "google-chrome", "google-chrome-stable"]:
|
||||||
|
path = shutil.which(name)
|
||||||
|
if path:
|
||||||
|
return path
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def port_listening(port):
|
||||||
|
"""Check if something is already listening on the given port."""
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.settimeout(1)
|
||||||
|
return s.connect_ex(("localhost", port)) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def try_connect(port):
|
||||||
|
"""Try to connect rodney to a browser on the given port. Returns True on success."""
|
||||||
|
result = subprocess.run(
|
||||||
|
["uvx", "rodney", "connect", "--local", f"localhost:{port}"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(f"Connected to existing browser on port {port}", file=sys.stderr)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def launch_system_browser(browser_path):
|
||||||
|
"""Launch a system browser with remote debugging and wait for it to be ready."""
|
||||||
|
subprocess.Popen(
|
||||||
|
[
|
||||||
|
browser_path,
|
||||||
|
"--headless",
|
||||||
|
"--disable-gpu",
|
||||||
|
f"--remote-debugging-port={REMOTE_DEBUG_PORT}",
|
||||||
|
"--no-sandbox",
|
||||||
|
],
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
# Wait for the browser to start listening
|
||||||
|
for _ in range(20):
|
||||||
|
if port_listening(REMOTE_DEBUG_PORT):
|
||||||
|
return True
|
||||||
|
time.sleep(0.25)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def start_browser():
|
||||||
|
"""Start a headless browser and connect rodney to it.
|
||||||
|
|
||||||
|
Strategy order (fastest path first):
|
||||||
|
1. Connect to an already-running browser on the debug port.
|
||||||
|
2. Launch a system Chrome/Chromium (avoids rodney's Chromium download,
|
||||||
|
which fails on some architectures like Linux ARM64).
|
||||||
|
3. Let rodney launch its own browser as a last resort.
|
||||||
|
"""
|
||||||
|
# Strategy 1: connect to an already-running browser
|
||||||
|
if port_listening(REMOTE_DEBUG_PORT) and try_connect(REMOTE_DEBUG_PORT):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Strategy 2: launch a system browser (most reliable on Linux)
|
||||||
|
browser = find_system_browser()
|
||||||
|
if browser:
|
||||||
|
print(f"Launching system browser: {browser}", file=sys.stderr)
|
||||||
|
if launch_system_browser(browser):
|
||||||
|
if try_connect(REMOTE_DEBUG_PORT):
|
||||||
|
return
|
||||||
|
print("WARNING: system browser started but rodney could not connect", file=sys.stderr)
|
||||||
|
else:
|
||||||
|
print("WARNING: system browser did not start in time", file=sys.stderr)
|
||||||
|
|
||||||
|
# Strategy 3: let rodney try its built-in launcher
|
||||||
|
result = subprocess.run(
|
||||||
|
["uvx", "rodney", "start", "--local"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print("Browser started via rodney", file=sys.stderr)
|
||||||
|
return
|
||||||
|
|
||||||
|
print(
|
||||||
|
"ERROR: Could not start a browser. Tried:\n"
|
||||||
|
f" - Connecting to localhost:{REMOTE_DEBUG_PORT} (no browser found)\n"
|
||||||
|
f" - System browser: {browser or 'not found'}\n"
|
||||||
|
" - rodney start (failed)\n"
|
||||||
|
"Install chromium or google-chrome and try again.",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_gitignore_entry(entry):
|
||||||
|
"""Add entry to .gitignore if the file exists and the entry is missing."""
|
||||||
|
gitignore = ".gitignore"
|
||||||
|
if not os.path.isfile(gitignore):
|
||||||
|
return
|
||||||
|
with open(gitignore, "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
# Check if the entry (with or without trailing slash/newline variations) is already present
|
||||||
|
lines = content.splitlines()
|
||||||
|
if any(line.strip() == entry or line.strip() == entry.rstrip("/") for line in lines):
|
||||||
|
return
|
||||||
|
# Append the entry
|
||||||
|
with open(gitignore, "a") as f:
|
||||||
|
if content and not content.endswith("\n"):
|
||||||
|
f.write("\n")
|
||||||
|
f.write(f"{entry}\n")
|
||||||
|
print(f"Added '{entry}' to .gitignore", file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(f"Usage: {sys.argv[0]} <slug> <report-title>", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
slug = sys.argv[1]
|
||||||
|
title = sys.argv[2]
|
||||||
|
|
||||||
|
# Create output directory
|
||||||
|
d = f".agent-tests/{datetime.date.today()}-{slug}"
|
||||||
|
os.makedirs(f"{d}/screenshots", exist_ok=True)
|
||||||
|
|
||||||
|
# Ensure .rodney/ is in .gitignore (rodney stores session files there)
|
||||||
|
ensure_gitignore_entry(".rodney/")
|
||||||
|
|
||||||
|
# Init showboat report
|
||||||
|
subprocess.run(["uvx", "showboat", "init", f"{d}/report.md", title], check=True)
|
||||||
|
|
||||||
|
# Start browser
|
||||||
|
start_browser()
|
||||||
|
|
||||||
|
# Print the directory path (only real stdout, everything else goes to stderr)
|
||||||
|
print(d)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -8,7 +8,9 @@
|
|||||||
"!.specify",
|
"!.specify",
|
||||||
"!specs",
|
"!specs",
|
||||||
"!coverage",
|
"!coverage",
|
||||||
"!.pnpm-store"
|
"!.pnpm-store",
|
||||||
|
"!.rodney",
|
||||||
|
"!.agent-tests"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"assist": {
|
"assist": {
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
|
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"undici": ">=7.24.0"
|
"undici": ">=7.24.0",
|
||||||
|
"picomatch": ">=4.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
31
pnpm-lock.yaml
generated
31
pnpm-lock.yaml
generated
@@ -6,6 +6,7 @@ settings:
|
|||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
undici: '>=7.24.0'
|
undici: '>=7.24.0'
|
||||||
|
picomatch: '>=4.0.4'
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
@@ -1082,7 +1083,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
|
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
picomatch: ^3 || ^4
|
picomatch: '>=4.0.4'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
picomatch:
|
picomatch:
|
||||||
optional: true
|
optional: true
|
||||||
@@ -1507,12 +1508,8 @@ packages:
|
|||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
picomatch@2.3.1:
|
picomatch@4.0.4:
|
||||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
|
||||||
engines: {node: '>=8.6'}
|
|
||||||
|
|
||||||
picomatch@4.0.3:
|
|
||||||
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
|
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
postcss@8.5.8:
|
postcss@8.5.8:
|
||||||
@@ -2663,9 +2660,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
walk-up-path: 4.0.0
|
walk-up-path: 4.0.0
|
||||||
|
|
||||||
fdir@6.5.0(picomatch@4.0.3):
|
fdir@6.5.0(picomatch@4.0.4):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.4
|
||||||
|
|
||||||
fill-range@7.1.1:
|
fill-range@7.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2865,7 +2862,7 @@ snapshots:
|
|||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
oxc-resolver: 11.19.1
|
oxc-resolver: 11.19.1
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.4
|
||||||
smol-toml: 1.6.0
|
smol-toml: 1.6.0
|
||||||
strip-json-comments: 5.0.3
|
strip-json-comments: 5.0.3
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
@@ -3002,7 +2999,7 @@ snapshots:
|
|||||||
micromatch@4.0.8:
|
micromatch@4.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
braces: 3.0.3
|
braces: 3.0.3
|
||||||
picomatch: 2.3.1
|
picomatch: 4.0.4
|
||||||
|
|
||||||
mimic-fn@2.1.0: {}
|
mimic-fn@2.1.0: {}
|
||||||
|
|
||||||
@@ -3100,9 +3097,7 @@ snapshots:
|
|||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@4.0.4: {}
|
||||||
|
|
||||||
picomatch@4.0.3: {}
|
|
||||||
|
|
||||||
postcss@8.5.8:
|
postcss@8.5.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3315,8 +3310,8 @@ snapshots:
|
|||||||
|
|
||||||
tinyglobby@0.2.15:
|
tinyglobby@0.2.15:
|
||||||
dependencies:
|
dependencies:
|
||||||
fdir: 6.5.0(picomatch@4.0.3)
|
fdir: 6.5.0(picomatch@4.0.4)
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.4
|
||||||
|
|
||||||
tinyrainbow@3.1.0: {}
|
tinyrainbow@3.1.0: {}
|
||||||
|
|
||||||
@@ -3356,7 +3351,7 @@ snapshots:
|
|||||||
vite@8.0.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.3):
|
vite@8.0.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
lightningcss: 1.32.0
|
lightningcss: 1.32.0
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.4
|
||||||
postcss: 8.5.8
|
postcss: 8.5.8
|
||||||
rolldown: 1.0.0-rc.10
|
rolldown: 1.0.0-rc.10
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
@@ -3380,7 +3375,7 @@ snapshots:
|
|||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
obug: 2.1.1
|
obug: 2.1.1
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.4
|
||||||
std-env: 4.0.0
|
std-env: 4.0.0
|
||||||
tinybench: 2.9.0
|
tinybench: 2.9.0
|
||||||
tinyexec: 1.0.4
|
tinyexec: 1.0.4
|
||||||
|
|||||||
Reference in New Issue
Block a user