diff --git a/.cursorignore b/.cursorignore index 4d390ae..706dcbb 100644 --- a/.cursorignore +++ b/.cursorignore @@ -8,4 +8,5 @@ /README.md /stack.production.yml /stack.staging.yml -/tests/ \ No newline at end of file +# /tests/ +Dockerfile.production \ No newline at end of file diff --git a/docker/package-lock.json b/docker/package-lock.json new file mode 100644 index 0000000..6d0d1da --- /dev/null +++ b/docker/package-lock.json @@ -0,0 +1,25 @@ +{ + "name": "docker", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "docker", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "xmldom": "^0.6.0" + } + }, + "node_modules/xmldom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", + "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + } + } +} diff --git a/docker/resume/Caddyfile b/docker/resume/Caddyfile index 697179c..4d58280 100644 --- a/docker/resume/Caddyfile +++ b/docker/resume/Caddyfile @@ -29,7 +29,7 @@ colinknapp.com { Cache-Control "public, max-age=31536000, immutable" # CSP with hashes for scripts and styles - Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-JR8sYN1/jgctBktEsjejl175usnuJQ+LimW18BWyL8I=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-5Lrk4RP6+4oP0Dbe2qVepxbZ0tYjXoWQHz55YlbGXFk=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" + Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-uTJNJlctGr5GxR5DKnz1Ex31vH0TR93OFGloxbHe65g=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-UUDFHb6NI63nBRS2EmyJq4giwjTQGYPq7uSTB4UQnPc=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544=' 'sha256-8CNR2aPoRsO94LHwXXZzxijfMf15BfwUewt8hvVbPcE='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-r0ECPtfllGARVL3R4rbe8FsQgyNZPyqJ6vkvvwXQpqM=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" } # Handle 404s @@ -79,7 +79,7 @@ colinknapp.com { Cache-Control "public, max-age=31536000, immutable" # CSP with hashes for scripts and styles - Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-JR8sYN1/jgctBktEsjejl175usnuJQ+LimW18BWyL8I=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-5Lrk4RP6+4oP0Dbe2qVepxbZ0tYjXoWQHz55YlbGXFk=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" + Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-uTJNJlctGr5GxR5DKnz1Ex31vH0TR93OFGloxbHe65g=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-UUDFHb6NI63nBRS2EmyJq4giwjTQGYPq7uSTB4UQnPc=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544=' 'sha256-8CNR2aPoRsO94LHwXXZzxijfMf15BfwUewt8hvVbPcE='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-r0ECPtfllGARVL3R4rbe8FsQgyNZPyqJ6vkvvwXQpqM=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" } # Handle 404s diff --git a/docker/resume/Caddyfile.local b/docker/resume/Caddyfile.local index 4232461..a377b74 100644 --- a/docker/resume/Caddyfile.local +++ b/docker/resume/Caddyfile.local @@ -39,6 +39,6 @@ Cache-Control "public, max-age=31536000, immutable" # CSP with hashes for scripts and styles - Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-JR8sYN1/jgctBktEsjejl175usnuJQ+LimW18BWyL8I=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-5Lrk4RP6+4oP0Dbe2qVepxbZ0tYjXoWQHz55YlbGXFk=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" + Content-Security-Policy "default-src 'none'; script-src 'self' 'sha256-oRCvBUmDTuPb8XOF1vLYwhIrcj2kzMbEwX5QzUPAPQI=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-uTJNJlctGr5GxR5DKnz1Ex31vH0TR93OFGloxbHe65g=' 'sha256-fOEWMJmrMxKbP5wElIXmDNUlfs6BSn+E9zt81T0Rysg=' 'sha256-q9ac7XWqnIASoBRfs4I4hpSMlnxGARofcEw0cSFfn/E=' 'sha256-+dDNTo7WAOmn2YC875+vn9oH4UkMwlVOGlARp2uq3A4=' 'sha256-1ZUvhca3M/N6hch4NrdPufDPLTnANOpJ4hfsZgRykgg=' 'sha256-UUDFHb6NI63nBRS2EmyJq4giwjTQGYPq7uSTB4UQnPc=' 'sha256-Ue6wom48SQbpmwW9QIk7pyVDR5Bg36SetP67V2pDkxc=' 'sha256-ryQsJ+aghKKD/CeXgx8jtsnZT3Epp3EjIw8RyHIq544=' 'sha256-8CNR2aPoRsO94LHwXXZzxijfMf15BfwUewt8hvVbPcE='; style-src 'self' 'sha256-5oTxos9Qxwhor3qIwHSM12YyIZi5E+tHuFdYER0hXoI=' 'sha256-807UZmWvd6eLc8xVckZkNX6CRP9WV8MzHURc5BgtRWo=' 'sha256-efXJB9ojE48KDEisFG5s+pGha1fH1bZA/IKW/ZKrL50=' 'sha256-r0ECPtfllGARVL3R4rbe8FsQgyNZPyqJ6vkvvwXQpqM=' 'sha256-2EA12+9d+s6rrc0rkdIjfmjbh6p2o0ZSXs4wbZuk/tA='; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';" } } diff --git a/docker/resume/Dockerfile b/docker/resume/Dockerfile index 57f3abe..dde1a56 100644 --- a/docker/resume/Dockerfile +++ b/docker/resume/Dockerfile @@ -1,43 +1,21 @@ -FROM caddy:2-alpine +FROM caddy:2.7-alpine -# Install required tools for hash calculation and CSP updates -RUN apk add --no-cache bash coreutils findutils grep sed xxd perl gawk - -# Copy update scripts first -COPY update-csp-hashes.sh /srv/update-csp-hashes.sh -COPY caddy.sh /srv/caddy.sh - -# Copy Caddyfile and static content -COPY Caddyfile /etc/caddy/Caddyfile -# Also copy to /srv for compatibility with the script -COPY Caddyfile /srv/Caddyfile -COPY index.html /srv/ -COPY theme.js /srv/ -COPY utils.js /srv/ -COPY styles.css /srv/ -COPY favicon.ico /srv/ -COPY includes.js /srv/ -COPY papaparse.min.js /srv/ - -# Copy one-pager-tools directory -COPY one-pager-tools /srv/one-pager-tools/ - -# Copy includes directory -COPY includes/ /srv/includes/ - -# Copy stories directory -COPY stories/ /srv/stories/ +# Install dependencies +RUN apk add --no-cache nodejs bash # Set working directory WORKDIR /srv -# Run the update-csp-hashes.sh script to update CSP hashes -RUN chmod +x /srv/caddy.sh /srv/update-csp-hashes.sh && \ - cd /srv && \ - ./update-csp-hashes.sh +# Copy website files +COPY . /srv -# Expose port 8080 +# Run all update scripts (sitemap, navigation, stories, CSP hashes, accessibility fixes) +RUN cd /srv && \ + chmod +x update-all.sh && \ + ./update-all.sh + +# Expose port EXPOSE 8080 -# Run Caddy -CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"] +# Start Caddy with the local Caddyfile +CMD ["caddy", "run", "--config", "/srv/Caddyfile.local"] diff --git a/docker/resume/Dockerfile.production b/docker/resume/Dockerfile.production index d3337ab..3fcf77b 100644 --- a/docker/resume/Dockerfile.production +++ b/docker/resume/Dockerfile.production @@ -1 +1 @@ -FROM git.nixc.us/colin/resume:staging \ No newline at end of file +FROM git.nixc.us/nixc/resume:staging diff --git a/docker/resume/csv-tool-output.html b/docker/resume/csv-tool-output.html index 074ea36..f3b3535 100644 --- a/docker/resume/csv-tool-output.html +++ b/docker/resume/csv-tool-output.html @@ -52,7 +52,7 @@ } - +
diff --git a/docker/resume/generate-sitemap.sh b/docker/resume/generate-sitemap.sh new file mode 100755 index 0000000..cc52b4e --- /dev/null +++ b/docker/resume/generate-sitemap.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# ===================================================================== +# generate-sitemap.sh - Generate sitemap.xml for the website +# ===================================================================== +# This script generates a sitemap.xml file for the website +# It should be run after any content updates +# ===================================================================== + +set -e + +echo "Generating sitemap.xml..." + +# Directory containing the files +BASE_DIR="$(pwd)" +DOMAIN="https://resume.example.com" # Replace with your actual domain in production + +# Get current date in ISO 8601 format +CURRENT_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") + +# Create sitemap header +cat > "$BASE_DIR/sitemap.xml" << EOF + +Read more about my open source success →
- -Accessibility: This website is designed and developed to meet WCAG 2.1 Level AAA standards, ensuring the highest level of accessibility for all users. Features include high contrast ratios, keyboard navigation, screen reader compatibility, and responsive design. The site supports both light and dark modes with automatic system preference detection.
diff --git a/docker/resume/one-pager-tools/csv-tool.html b/docker/resume/one-pager-tools/csv-tool.html index dc2d36b..8db54b0 100644 --- a/docker/resume/one-pager-tools/csv-tool.html +++ b/docker/resume/one-pager-tools/csv-tool.html @@ -52,7 +52,7 @@ } - + diff --git a/docker/resume/one-pager-tools/template.html b/docker/resume/one-pager-tools/template.html index f8ff1ca..41fcebe 100644 --- a/docker/resume/one-pager-tools/template.html +++ b/docker/resume/one-pager-tools/template.html @@ -13,7 +13,7 @@ - + diff --git a/docker/resume/one-pager-tools/tool-with-includes.html b/docker/resume/one-pager-tools/tool-with-includes.html index 3337250..8a7d6a1 100644 --- a/docker/resume/one-pager-tools/tool-with-includes.html +++ b/docker/resume/one-pager-tools/tool-with-includes.html @@ -13,7 +13,7 @@ - + diff --git a/docker/resume/sitemap.xml b/docker/resume/sitemap.xml new file mode 100644 index 0000000..aface3d --- /dev/null +++ b/docker/resume/sitemap.xml @@ -0,0 +1,99 @@ + +How I revitalized an abandoned open source project, built a thriving community of 32,000+ members, and established sustainable funding.
- - Read Full Story -How I built an AI-powered cybersecurity consultancy from the ground up, focusing on cutting-edge protection for digital assets.
- - Read Full Story -The technical challenges overcome in scaling Minecraft world editing from crashing at 50,000 edits to seamlessly handling billions.
- - Read Full Story -Designing custom video games for prominent online creators while integrating advanced cybersecurity measures.
- - Read Full Story -Developing web solutions and Java plugins with a focus on CI/CD efficiency and accessibility standards.
- - Read Full Story -Creating an ad revenue tracking app to help content creators optimize their earnings and content strategies.
- - Read Full Story -An in-depth look at the infrastructure design and security implementation for the Improving MI Practices healthcare platform.
- - Read Full Story -How I developed a Docker-based solution that eliminated persistent malware attacks on a high-profile website.
- - Read Full Story -Building a geographically redundant DNS cluster for Flint Bishop International Airport that achieves A+ reliability standards.
- +Category: Infrastructure & Resilience | Date: 2019-Present...
+ Read Full StoryManaging a distributed team of 45 contractors and implementing DevSecOps practices across multiple timezones.
- - Read Full Story +Category: Mobile Development, Analytics | Date: 2013-2018...
+ + Read Full StoryTransforming a struggling business into a self-sustaining operation in just two weeks through strategic optimization.
- +Category: Business Turnaround, System Optimization | Date: 2013-2017...
+ Read Full StoryCategory: Open Source Development | Date: 2014-Present...
+ + Read Full Story +Category: Infrastructure & Security | Date: 2019-Present...
+ + Read Full Story +Co-founding a company dedicated to reducing electronic waste through specialized circuit board repair services.
- +Category: Entrepreneurship, Sustainable Technology | Date: 2019-Present...
+ Read Full StoryCategory: Team Leadership & DevOps | Date: 2018-2021...
+ + Read Full Story +Category: Open Source | Date: 2019-Present...
+ + Read Full Story +Revamping the website for an eco-friendly recirculating shower system with a focus on accessibility and modern design.
- +Category: Web Development, Sustainability | Date: 2016...
+ Read Full StoryCategory: Cybersecurity | Date: 2023-Present...
+ + Read Full Story +Category: Web Development, Java | Date: 2009-2023...
+ + Read Full Story +Category: Security & Automation | Date: 2023...
+ + Read Full Story +Category: Game Development, Cybersecurity | Date: 2009-2022...
+ + Read Full Story +Accessibility: This website is designed and developed to meet WCAG 2.1 Level AAA standards, ensuring the highest level of accessibility for all users. Features include high contrast ratios, keyboard navigation, screen reader compatibility, and responsive design. The site supports both light and dark modes with automatic system preference detection.
diff --git a/docker/resume/stories/motherboard-repair.html b/docker/resume/stories/motherboard-repair.html index e6f8b2b..77d2554 100644 --- a/docker/resume/stories/motherboard-repair.html +++ b/docker/resume/stories/motherboard-repair.html @@ -9,9 +9,9 @@ - + - + diff --git a/docker/resume/stories/nitric-leadership.html b/docker/resume/stories/nitric-leadership.html index 9124a5c..6314141 100644 --- a/docker/resume/stories/nitric-leadership.html +++ b/docker/resume/stories/nitric-leadership.html @@ -9,9 +9,9 @@ - + - + diff --git a/docker/resume/stories/open-source-success.html b/docker/resume/stories/open-source-success.html index bbf7fdb..e3bfb06 100644 --- a/docker/resume/stories/open-source-success.html +++ b/docker/resume/stories/open-source-success.html @@ -9,9 +9,9 @@ - + - + diff --git a/docker/resume/stories/showerloop.html b/docker/resume/stories/showerloop.html index 1243789..bd1e26a 100644 --- a/docker/resume/stories/showerloop.html +++ b/docker/resume/stories/showerloop.html @@ -9,9 +9,9 @@ - + - + diff --git a/docker/resume/stories/stories.css b/docker/resume/stories/stories.css index 605ff79..71f9ce0 100644 --- a/docker/resume/stories/stories.css +++ b/docker/resume/stories/stories.css @@ -156,11 +156,13 @@ border-radius: 4px; text-decoration: none; transition: all 0.3s ease; + color: #004494; } .story-nav-link:hover { background-color: var(--theme-hover); text-decoration: none; + color: #003366; } .story-nav-link.prev::before { @@ -240,6 +242,10 @@ .placeholder-notice a { font-weight: bold; - color: var(--accent-color); + color: #004494; text-decoration: underline; +} + +.placeholder-notice a:hover { + color: #003366; } \ No newline at end of file diff --git a/docker/resume/stories/stories.css.fixed b/docker/resume/stories/stories.css.fixed new file mode 100644 index 0000000..b52cacf --- /dev/null +++ b/docker/resume/stories/stories.css.fixed @@ -0,0 +1,216 @@ +/* Story-specific styles */ +.story-container { + max-width: 800px; + margin: 0 auto; + padding: 20px; + background-color: #f5f5f5; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.story-header { + margin-bottom: 20px; + text-align: center; +} + +.story-header h1 { + font-size: 2em; + margin-bottom: 10px; +} + +.story-meta { + font-style: italic; + color: #555; + margin-bottom: 10px; +} + +.story-content { + line-height: 1.6; +} + +.story-content p { + margin-bottom: 15px; +} + +.story-content h2 { + margin-top: 30px; + margin-bottom: 15px; + font-size: 1.5em; +} + +.story-content h3 { + margin-top: 25px; + margin-bottom: 10px; + font-size: 1.3em; +} + +.story-content ul, .story-content ol { + margin-bottom: 15px; + margin-left: 20px; +} + +.story-content li { + margin-bottom: 5px; +} + +.story-content blockquote { + margin: 20px 0; + padding: 10px 20px; + border-left: 4px solid #ccc; + background-color: #f9f9f9; + font-style: italic; +} + +.story-content img { + max-width: 100%; + height: auto; + margin: 20px 0; + display: block; +} + +.story-content .image-caption { + text-align: center; + font-style: italic; + margin-top: -15px; + margin-bottom: 20px; + color: #666; +} + +.story-content code { + font-family: monospace; + background-color: #f0f0f0; + padding: 2px 4px; + border-radius: 3px; +} + +.story-content pre { + background-color: #f0f0f0; + padding: 15px; + border-radius: 5px; + overflow-x: auto; + margin-bottom: 20px; +} + +.story-content pre code { + background-color: transparent; + padding: 0; +} + +.story-navigation { + display: flex; + justify-content: space-between; + margin-top: 30px; + padding-top: 20px; + border-top: 1px solid #ddd; +} + +.story-nav-link { + padding: 8px 15px; + background-color: #f0f0f0; + color: #004494; /* Darker blue for 7:1+ contrast ratio */ + text-decoration: none; + border-radius: 4px; + transition: background-color 0.2s; +} + +.story-nav-link:hover { + background-color: #e0e0e0; +} + +.story-nav-link.prev::before { + content: "← "; +} + +.story-nav-link.next::after { + content: " →"; +} + +.story-tags { + margin-top: 20px; + font-size: 0.9em; +} + +.story-tag { + display: inline-block; + background-color: #e0e0e0; + color: #333; + padding: 3px 8px; + margin-right: 5px; + margin-bottom: 5px; + border-radius: 3px; +} + +/* Story index page styles */ +.stories-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 20px; + margin-top: 20px; +} + +.story-card { + background-color: #f5f5f5; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + overflow: hidden; + transition: transform 0.2s, box-shadow 0.2s; +} + +.story-card:hover { + transform: translateY(-5px); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); +} + +.story-card-content { + padding: 15px; +} + +.story-card h2 { + margin-top: 0; + margin-bottom: 10px; + font-size: 1.3em; +} + +.story-card p { + margin-bottom: 15px; + color: #555; + font-size: 0.9em; +} + +.story-card-link { + display: inline-block; + padding: 5px 10px; + background-color: #f0f0f0; + color: #004494; /* Darker blue for 7:1+ contrast ratio */ + text-decoration: none; + border-radius: 3px; + font-size: 0.9em; + transition: background-color 0.2s; +} + +.story-card-link:hover { + background-color: #e0e0e0; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .stories-grid { + grid-template-columns: 1fr; + } + + .story-container { + padding: 15px; + } + + .story-header h1 { + font-size: 1.8em; + } + + .story-content h2 { + font-size: 1.4em; + } + + .story-content h3 { + font-size: 1.2em; + } +} diff --git a/docker/resume/stories/story-with-includes.html b/docker/resume/stories/story-with-includes.html index 39c1b49..d465183 100644 --- a/docker/resume/stories/story-with-includes.html +++ b/docker/resume/stories/story-with-includes.html @@ -7,11 +7,11 @@]*>(.*?)<\/p>/is);
+ if (excerptMatch && excerptMatch[1]) {
+ metadata.excerpt = excerptMatch[1].trim().substring(0, 150) + '...';
+ }
+
+ // Try to extract category and date
+ const categoryMatch = content.match(/Category:<\/strong>\s*(.*?)(?:<|$)/i);
+ if (categoryMatch && categoryMatch[1]) {
+ metadata.category = categoryMatch[1].trim();
+ }
+
+ const dateMatch = content.match(/(?:Date|Timeframe):<\/strong>\s*(.*?)(?:<|$)/i);
+ if (dateMatch && dateMatch[1]) {
+ metadata.date = dateMatch[1].trim();
+ }
+
+ return metadata;
+ } catch (error) {
+ console.error(`Error extracting metadata from ${storyPath}:`, error);
+ return {
+ title: getFriendlyName(path.basename(storyPath)),
+ excerpt: 'Detailed case study and project information.',
+ category: 'Project',
+ date: 'Recent'
+ };
+ }
+}
+
+// Main function
+async function updateStoriesPage() {
+ try {
+ console.log('Updating stories page from sitemap.xml...');
+
+ // Check if sitemap.xml exists
+ if (!fs.existsSync(SITEMAP_PATH)) {
+ console.error('Sitemap.xml not found at:', SITEMAP_PATH);
+ return;
+ }
+
+ // Check if stories/index.html exists
+ if (!fs.existsSync(STORIES_INDEX_PATH)) {
+ console.error('Stories index page not found at:', STORIES_INDEX_PATH);
+ return;
+ }
+
+ // Read sitemap.xml
+ const sitemapContent = fs.readFileSync(SITEMAP_PATH, 'utf8');
+ const allUrls = extractUrlsFromSitemap(sitemapContent);
+
+ // Find all story URLs in sitemap
+ const storyUrls = [];
+
+ for (const url of allUrls) {
+ if (url.includes(STORIES_PATH_PREFIX)) {
+ const filename = url.split('/').pop();
+ if (!STORIES_PATH_EXCLUDE.includes(filename)) {
+ storyUrls.push({
+ url: url,
+ filename: filename
+ });
+ }
+ }
+ }
+
+ console.log(`Found ${storyUrls.length} story pages in sitemap.`);
+
+ // Read stories/index.html
+ const storiesIndexContent = fs.readFileSync(STORIES_INDEX_PATH, 'utf8');
+
+ // Extract metadata for each story
+ const storyCards = [];
+
+ for (const storyUrl of storyUrls) {
+ const storyPath = path.join(__dirname, 'stories', storyUrl.filename);
+ if (fs.existsSync(storyPath)) {
+ const metadata = await extractStoryMetadata(storyPath);
+ storyCards.push({
+ filename: storyUrl.filename,
+ title: metadata.title,
+ excerpt: metadata.excerpt,
+ category: metadata.category,
+ date: metadata.date
+ });
+ }
+ }
+
+ // Generate HTML for story cards
+ let storiesGridHtml = ' Generated on: ${new Date(report.timestamp).toLocaleString()} ${report.summary.totalIssues} issues found across ${report.summary.pagesWithIssues} pages (${report.summary.totalPages} pages tested) Issues by impact: No color contrast issues found. Foreground: ${pair.foreground} Background: ${pair.background} Current contrast ratio: ${pair.currentRatio} (Required: ${pair.requiredRatio}) Found on ${pair.elementCount} element${pair.elementCount !== 1 ? 's' : ''} across ${pair.pagesAffected.length} page${pair.pagesAffected.length !== 1 ? 's' : ''} Pages affected: ${fix.description}
/,
+ `${storiesGridHtml}\n\n
`
+ );
+
+ // Write the updated content back to the file
+ fs.writeFileSync(STORIES_INDEX_PATH, updatedContent, 'utf8');
+
+ console.log(`Updated stories page with ${storyCards.length} story cards.`);
+ } catch (error) {
+ console.error('Error updating stories page:', error);
+ }
+}
+
+// Run the main function
+updateStoriesPage();
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 7c26a4e..101f322 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,37 +1,17 @@
{
- "name": "resume",
+ "name": "resume-site",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "resume",
+ "name": "resume-site",
"version": "1.0.0",
- "license": "ISC",
- "dependencies": {
- "express": "^4.18.2",
- "lighthouse": "^11.6.0",
- "playwright": "^1.42.1"
- },
"devDependencies": {
- "@axe-core/playwright": "^4.10.1",
- "@playwright/test": "^1.52.0",
- "chrome-launcher": "^1.1.2",
- "lighthouse": "^11.4.0",
- "puppeteer": "^22.4.1"
- }
- },
- "node_modules/@axe-core/playwright": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.10.1.tgz",
- "integrity": "sha512-EV5t39VV68kuAfMKqb/RL+YjYKhfuGim9rgIaQ6Vntb2HgaCaau0h98Y3WEUqW1+PbdzxDtDNjFAipbtZuBmEA==",
- "dev": true,
- "license": "MPL-2.0",
- "dependencies": {
- "axe-core": "~4.10.2"
- },
- "peerDependencies": {
- "playwright-core": ">= 1.0.0"
+ "axe-core": "^4.10.3",
+ "lighthouse": "^10.0.0",
+ "pa11y": "^9.0.0",
+ "playwright": "^1.53.2"
}
},
"node_modules/@babel/code-frame": {
@@ -59,99 +39,19 @@
"node": ">=6.9.0"
}
},
- "node_modules/@formatjs/ecma402-abstract": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz",
- "integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@formatjs/fast-memoize": "2.2.7",
- "@formatjs/intl-localematcher": "0.6.1",
- "decimal.js": "^10.4.3",
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@formatjs/fast-memoize": {
- "version": "2.2.7",
- "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz",
- "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@formatjs/icu-messageformat-parser": {
- "version": "2.11.2",
- "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz",
- "integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@formatjs/ecma402-abstract": "2.3.4",
- "@formatjs/icu-skeleton-parser": "1.8.14",
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@formatjs/icu-skeleton-parser": {
- "version": "1.8.14",
- "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz",
- "integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@formatjs/ecma402-abstract": "2.3.4",
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@formatjs/intl-localematcher": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz",
- "integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@paulirish/trace_engine": {
- "version": "0.0.19",
- "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.19.tgz",
- "integrity": "sha512-3tjEzXBBtU83DkCJAdU2UwBBunspiwTCn+Y5jOxm592cfEuLr/T7Lcn+QhRerVqkSik2mnjN4X6NgHZjI9Biwg==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "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/@puppeteer/browsers": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz",
- "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==",
+ "version": "2.10.5",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz",
+ "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "debug": "^4.3.5",
+ "debug": "^4.4.1",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
- "proxy-agent": "^6.4.0",
- "semver": "^7.6.3",
- "tar-fs": "^3.0.6",
- "unbzip2-stream": "^1.4.3",
+ "proxy-agent": "^6.5.0",
+ "semver": "^7.7.2",
+ "tar-fs": "^3.0.8",
"yargs": "^17.7.2"
},
"bin": {
@@ -162,9 +62,9 @@
}
},
"node_modules/@puppeteer/browsers/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -187,9 +87,9 @@
"license": "MIT"
},
"node_modules/@puppeteer/browsers/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -353,19 +253,6 @@
"@types/node": "*"
}
},
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -447,12 +334,6 @@
"dev": true,
"license": "Python-2.0"
},
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
"node_modules/ast-types": {
"version": "0.13.4",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
@@ -492,9 +373,9 @@
"optional": true
},
"node_modules/bare-fs": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz",
- "integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==",
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.6.tgz",
+ "integrity": "sha512-25RsLF33BqooOEFNdMcEhMpJy8EoR88zSMrnOQOaM3USnOK2VmaJ1uaQEwPA6AQjrv1lXChScosN6CzbwbO9OQ==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
@@ -591,28 +472,20 @@
"node": ">=10.0.0"
}
},
- "node_modules/body-parser": {
- "version": "1.20.3",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
- "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "node_modules/bfj": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/bfj/-/bfj-9.1.2.tgz",
+ "integrity": "sha512-EetpSUewwznXQ7yRtxHCgE5RLZV718n9cOYXe5BlhYKuNs0UkidHaUOe6Jlgbf+viGTQeg8mYhm5Wr4c2AB3gA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.13.0",
- "raw-body": "2.5.2",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
+ "check-types": "^11.2.3",
+ "hoopy": "^0.1.4",
+ "jsonpath": "^1.1.1",
+ "tryer": "^1.0.1"
},
"engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "node": ">= 18.0.0"
}
},
"node_modules/buffer": {
@@ -650,44 +523,6 @@
"node": "*"
}
},
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -698,17 +533,24 @@
"node": ">=6"
}
},
+ "node_modules/check-types": {
+ "version": "11.2.3",
+ "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz",
+ "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/chrome-launcher": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.1.2.tgz",
- "integrity": "sha512-YclTJey34KUm5jB1aEJCq807bSievi7Nb/TU4Gu504fUYi3jw3KCIaH6L7nFWQhdEgH3V+wCh+kKD1P5cXnfxw==",
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+ "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/node": "*",
"escape-string-regexp": "^4.0.0",
"is-wsl": "^2.2.0",
- "lighthouse-logger": "^2.0.1"
+ "lighthouse-logger": "^1.0.0"
},
"bin": {
"print-chrome-path": "bin/print-chrome-path.js"
@@ -718,15 +560,14 @@
}
},
"node_modules/chromium-bidi": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz",
- "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz",
+ "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "mitt": "3.0.1",
- "urlpattern-polyfill": "10.0.0",
- "zod": "3.23.8"
+ "mitt": "^3.0.1",
+ "zod": "^3.24.1"
},
"peerDependencies": {
"devtools-protocol": "*"
@@ -767,6 +608,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/commander": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
+ "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/configstore": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
@@ -785,27 +636,6 @@
"node": ">=8"
}
},
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
@@ -816,12 +646,6 @@
"node": ">= 0.6"
}
},
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
"node_modules/cosmiconfig": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
@@ -849,6 +673,16 @@
}
}
},
+ "node_modules/cross-fetch": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
+ "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
"node_modules/crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
@@ -880,15 +714,16 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
- "node_modules/decimal.js": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
- "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true,
"license": "MIT"
},
@@ -917,29 +752,24 @@
"node": ">= 14"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
+ "node_modules/degenerator/node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
"engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "node": ">=4"
}
},
"node_modules/devtools-protocol": {
- "version": "0.0.1232444",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz",
- "integrity": "sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==",
+ "version": "0.0.1464554",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1464554.tgz",
+ "integrity": "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw==",
"dev": true,
"license": "BSD-3-Clause"
},
@@ -956,26 +786,6 @@
"node": ">=8"
}
},
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -983,19 +793,10 @@
"dev": true,
"license": "MIT"
},
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1026,6 +827,19 @@
"node": ">=6"
}
},
+ "node_modules/envinfo": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz",
+ "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -1036,36 +850,6 @@
"is-arrayish": "^0.2.1"
}
},
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -1076,12 +860,6 @@
"node": ">=6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -1117,7 +895,7 @@
"source-map": "~0.6.1"
}
},
- "node_modules/esprima": {
+ "node_modules/escodegen/node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
@@ -1131,6 +909,19 @@
"node": ">=4"
}
},
+ "node_modules/esprima": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
+ "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
@@ -1151,70 +942,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.21.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
- "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "1.20.3",
- "content-disposition": "0.5.4",
- "content-type": "~1.0.4",
- "cookie": "0.7.1",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "1.3.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "6.13.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "0.19.0",
- "serve-static": "1.16.2",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express/node_modules/cookie": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
- "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -1237,9 +964,9 @@
}
},
"node_modules/extract-zip/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1268,6 +995,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@@ -1278,46 +1012,11 @@
"pend": "~1.2.0"
}
},
- "node_modules/finalhandler": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
- "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "2.0.1",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"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,
@@ -1332,6 +1031,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1347,43 +1047,6 @@
"node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
@@ -1416,9 +1079,9 @@
}
},
"node_modules/get-uri/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1440,18 +1103,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -1459,22 +1110,11 @@
"dev": true,
"license": "ISC"
},
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -1483,20 +1123,24 @@
"node": ">= 0.4"
}
},
- "node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "node_modules/hoopy": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
+ "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
- },
"engines": {
- "node": ">= 0.8"
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/html_codesniffer": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.5.1.tgz",
+ "integrity": "sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/http-link-header": {
@@ -1534,9 +1178,9 @@
}
},
"node_modules/http-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1597,18 +1241,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -1664,25 +1296,24 @@
"node": ">=0.8.19"
}
},
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
"node_modules/intl-messageformat": {
- "version": "10.7.16",
- "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz",
- "integrity": "sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz",
+ "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
- "@formatjs/ecma402-abstract": "2.3.4",
- "@formatjs/fast-memoize": "2.2.7",
- "@formatjs/icu-messageformat-parser": "2.11.2",
- "tslib": "^2.8.0"
+ "intl-messageformat-parser": "^1.8.1"
}
},
+ "node_modules/intl-messageformat-parser": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz",
+ "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==",
+ "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
@@ -1697,13 +1328,14 @@
"node": ">= 12"
}
},
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "node_modules/is": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz",
+ "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.10"
+ "node": "*"
}
},
"node_modules/is-arrayish": {
@@ -1820,39 +1452,73 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/jsonpath": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz",
+ "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esprima": "1.2.2",
+ "static-eval": "2.0.2",
+ "underscore": "1.12.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/lighthouse": {
- "version": "11.7.1",
- "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-11.7.1.tgz",
- "integrity": "sha512-QuvkZvobZ8Gjv2Jkxl6TKhV5JYBzU+lzpqTY+Y1iH5IUc1SMYK4IOpBnSpp6PkM2FbNyur9uoNutPhsuLLqGTg==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-10.4.0.tgz",
+ "integrity": "sha512-XQWHEWkJ8YxSPsxttBJORy5+hQrzbvGkYfeP3fJjyYKioWkF2MXfFqNK4ZuV4jL8pBu7Z91qnQP6In0bq1yXww==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@paulirish/trace_engine": "^0.0.19",
"@sentry/node": "^6.17.4",
- "axe-core": "^4.9.0",
- "chrome-launcher": "^1.1.1",
+ "axe-core": "4.7.2",
+ "chrome-launcher": "^0.15.2",
"configstore": "^5.0.1",
"csp_evaluator": "1.1.1",
- "devtools-protocol": "0.0.1232444",
+ "devtools-protocol": "0.0.1155343",
"enquirer": "^2.3.6",
"http-link-header": "^1.1.1",
- "intl-messageformat": "^10.5.3",
+ "intl-messageformat": "^4.4.0",
"jpeg-js": "^0.4.4",
- "js-library-detector": "^6.7.0",
- "lighthouse-logger": "^2.0.1",
- "lighthouse-stack-packs": "1.12.1",
+ "js-library-detector": "^6.6.0",
+ "lighthouse-logger": "^1.4.1",
+ "lighthouse-stack-packs": "1.11.0",
"lodash": "^4.17.21",
"lookup-closest-locale": "6.2.0",
"metaviewport-parser": "0.3.0",
"open": "^8.4.0",
"parse-cache-control": "1.0.1",
"ps-list": "^8.0.0",
- "puppeteer-core": "^22.5.0",
- "robots-parser": "^3.0.1",
+ "puppeteer-core": "^20.8.0",
+ "robots-parser": "^3.0.0",
"semver": "^5.3.0",
"speedline-core": "^1.4.3",
- "third-party-web": "^0.24.1",
- "tldts-icann": "^6.1.0",
+ "third-party-web": "^0.23.3",
"ws": "^7.0.0",
"yargs": "^17.3.1",
"yargs-parser": "^21.0.0"
@@ -1863,13 +1529,13 @@
"smokehouse": "cli/test/smokehouse/frontends/smokehouse-bin.js"
},
"engines": {
- "node": ">=18.16"
+ "node": ">=16.16"
}
},
"node_modules/lighthouse-logger": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-2.0.1.tgz",
- "integrity": "sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+ "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1878,12 +1544,234 @@
}
},
"node_modules/lighthouse-stack-packs": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.12.1.tgz",
- "integrity": "sha512-i4jTmg7tvZQFwNFiwB+nCK6a7ICR68Xcwo+VIVd6Spi71vBNFUlds5HiDrSbClZdkQDON2Bhqv+KKJIo5zkPeA==",
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.11.0.tgz",
+ "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==",
"dev": true,
"license": "Apache-2.0"
},
+ "node_modules/lighthouse/node_modules/@puppeteer/browsers": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz",
+ "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "4.3.4",
+ "extract-zip": "2.0.1",
+ "progress": "2.0.3",
+ "proxy-agent": "6.3.0",
+ "tar-fs": "3.0.4",
+ "unbzip2-stream": "1.4.3",
+ "yargs": "17.7.1"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=16.3.0"
+ },
+ "peerDependencies": {
+ "typescript": ">= 4.7.4"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lighthouse/node_modules/agent-base": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
+ "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/lighthouse/node_modules/axe-core": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz",
+ "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lighthouse/node_modules/chromium-bidi": {
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz",
+ "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mitt": "3.0.0"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
+ }
+ },
+ "node_modules/lighthouse/node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lighthouse/node_modules/devtools-protocol": {
+ "version": "0.0.1155343",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz",
+ "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/lighthouse/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/lighthouse/node_modules/mitt": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz",
+ "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lighthouse/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lighthouse/node_modules/proxy-agent": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz",
+ "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.0",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.0",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/lighthouse/node_modules/puppeteer-core": {
+ "version": "20.9.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz",
+ "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@puppeteer/browsers": "1.4.6",
+ "chromium-bidi": "0.4.16",
+ "cross-fetch": "4.0.0",
+ "debug": "4.3.4",
+ "devtools-protocol": "0.0.1147663",
+ "ws": "8.13.0"
+ },
+ "engines": {
+ "node": ">=16.3.0"
+ },
+ "peerDependencies": {
+ "typescript": ">= 4.7.4"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/devtools-protocol": {
+ "version": "0.0.1147663",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz",
+ "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/ws": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lighthouse/node_modules/tar-fs": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz",
+ "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ }
+ },
+ "node_modules/lighthouse/node_modules/yargs": {
+ "version": "17.7.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
+ "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -1949,39 +1837,12 @@
}
},
"node_modules/marky": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz",
- "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
+ "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
"dev": true,
"license": "Apache-2.0"
},
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/metaviewport-parser": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz",
@@ -1989,48 +1850,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
@@ -2038,19 +1857,28 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "node_modules/mustache": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
+ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.6"
+ "bin": {
+ "mustache": "bin/mustache"
}
},
"node_modules/netmask": {
@@ -2063,28 +1891,39 @@
"node": ">= 0.4.0"
}
},
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "ee-first": "1.1.1"
+ "whatwg-url": "^5.0.0"
},
"engines": {
- "node": ">= 0.8"
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node.extend": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.3.tgz",
+ "integrity": "sha512-xwADg/okH48PvBmRZyoX8i8GJaKuJ1CqlqotlZOhUio8egD1P5trJupHKBzcPjSF9ifK2gPcEICRBnkfPqQXZw==",
+ "dev": true,
+ "license": "(MIT OR GPL-2.0)",
+ "dependencies": {
+ "hasown": "^2.0.0",
+ "is": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
}
},
"node_modules/once": {
@@ -2115,6 +1954,62 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pa11y": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-9.0.0.tgz",
+ "integrity": "sha512-IGOctP9ETUGZ+ygzX7co6p4BhImdtQ0HDHFMdjyReUXb3dzmR14HeHCUja88bCTnnnl2/FG17h6zZeD5GjQvSg==",
+ "dev": true,
+ "license": "LGPL-3.0-only",
+ "dependencies": {
+ "axe-core": "~4.10.3",
+ "bfj": "~9.1.2",
+ "commander": "~13.1.0",
+ "envinfo": "~7.14.0",
+ "html_codesniffer": "~2.5.1",
+ "kleur": "~4.1.5",
+ "mustache": "~4.2.0",
+ "node.extend": "~2.0.3",
+ "puppeteer": "^24.7.2",
+ "semver": "~7.7.1"
+ },
+ "bin": {
+ "pa11y": "bin/pa11y.js"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/pa11y/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/pac-proxy-agent": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
@@ -2146,9 +2041,9 @@
}
},
"node_modules/pac-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2236,21 +2131,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
- "license": "MIT"
- },
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -2266,12 +2146,13 @@
"license": "ISC"
},
"node_modules/playwright": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz",
- "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==",
+ "version": "1.53.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.2.tgz",
+ "integrity": "sha512-6K/qQxVFuVQhRQhFsVZ9fGeatxirtrpPgxzBYWyZLEXJzqYwuL4fuNmfOfD5et1tJE4GScKyPNeLhZeRwuTU3A==",
+ "dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.52.0"
+ "playwright-core": "1.53.2"
},
"bin": {
"playwright": "cli.js"
@@ -2283,10 +2164,11 @@
"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==",
+ "node_modules/playwright/node_modules/playwright-core": {
+ "version": "1.53.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.2.tgz",
+ "integrity": "sha512-ox/OytMy+2w1jcYEYlOo1Hhp8hZkLCximMTUTMBXjGUA1KoFfiSZ+DU+3a739jsPY0yoKH2TFy9S2fsJas8yAw==",
+ "dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
@@ -2295,6 +2177,15 @@
"node": ">=18"
}
},
+ "node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -2305,19 +2196,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/proxy-agent": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
@@ -2349,9 +2227,9 @@
}
},
"node_modules/proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2408,9 +2286,9 @@
}
},
"node_modules/pump": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
- "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
+ "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2419,46 +2297,49 @@
}
},
"node_modules/puppeteer": {
- "version": "22.15.0",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz",
- "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==",
+ "version": "24.11.2",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.11.2.tgz",
+ "integrity": "sha512-HopdRZWHa5zk0HSwd8hU+GlahQ3fmesTAqMIDHVY9HasCvppcYuHYXyjml0nlm+nbwVCqAQWV+dSmiNCrZGTGQ==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@puppeteer/browsers": "2.3.0",
+ "@puppeteer/browsers": "2.10.5",
+ "chromium-bidi": "5.1.0",
"cosmiconfig": "^9.0.0",
- "devtools-protocol": "0.0.1312386",
- "puppeteer-core": "22.15.0"
+ "devtools-protocol": "0.0.1464554",
+ "puppeteer-core": "24.11.2",
+ "typed-query-selector": "^2.12.0"
},
"bin": {
- "puppeteer": "lib/esm/puppeteer/node/cli.js"
+ "puppeteer": "lib/cjs/puppeteer/node/cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/puppeteer-core": {
- "version": "22.15.0",
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz",
- "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==",
+ "version": "24.11.2",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.11.2.tgz",
+ "integrity": "sha512-c49WifNb8hix+gQH17TldmD6TC/Md2HBaTJLHexIUq4sZvo2pyHY/Pp25qFQjibksBu/SJRYUY7JsoaepNbiRA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@puppeteer/browsers": "2.3.0",
- "chromium-bidi": "0.6.3",
- "debug": "^4.3.6",
- "devtools-protocol": "0.0.1312386",
- "ws": "^8.18.0"
+ "@puppeteer/browsers": "2.10.5",
+ "chromium-bidi": "5.1.0",
+ "debug": "^4.4.1",
+ "devtools-protocol": "0.0.1464554",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/puppeteer-core/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2473,13 +2354,6 @@
}
}
},
- "node_modules/puppeteer-core/node_modules/devtools-protocol": {
- "version": "0.0.1312386",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
- "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
"node_modules/puppeteer-core/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -2488,9 +2362,9 @@
"license": "MIT"
},
"node_modules/puppeteer-core/node_modules/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2509,52 +2383,6 @@
}
}
},
- "node_modules/puppeteer/node_modules/devtools-protocol": {
- "version": "0.0.1312386",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
- "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "node_modules/qs": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
- "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.0.6"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
- "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -2585,32 +2413,6 @@
"node": ">=10.0.0"
}
},
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
"node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
@@ -2621,138 +2423,6 @@
"semver": "bin/semver"
}
},
- "node_modules/send": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
- "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "2.0.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/serve-static": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
- "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.19.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
@@ -2772,9 +2442,9 @@
}
},
"node_modules/socks": {
- "version": "2.8.4",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
- "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
+ "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2812,9 +2482,9 @@
}
},
"node_modules/socks-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2869,19 +2539,67 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "node_modules/static-eval": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
+ "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "escodegen": "^1.8.1"
+ }
+ },
+ "node_modules/static-eval/node_modules/escodegen": {
+ "version": "1.14.3",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+ "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
"engines": {
- "node": ">= 0.8"
+ "node": ">=4.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/static-eval/node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/static-eval/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
}
},
"node_modules/streamx": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz",
- "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==",
+ "version": "2.22.1",
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz",
+ "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2921,9 +2639,9 @@
}
},
"node_modules/tar-fs": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz",
- "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
+ "integrity": "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2958,9 +2676,9 @@
}
},
"node_modules/third-party-web": {
- "version": "0.24.5",
- "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.24.5.tgz",
- "integrity": "sha512-1rUOdMYpNTRajgk1F7CmHD26oA6rTKekBjHay854J6OkPXeNyPcR54rhWDaamlWyi9t2wAVPQESdedBhucmOLA==",
+ "version": "0.23.4",
+ "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.23.4.tgz",
+ "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==",
"dev": true,
"license": "MIT"
},
@@ -2971,31 +2689,19 @@
"dev": true,
"license": "MIT"
},
- "node_modules/tldts-core": {
- "version": "6.1.85",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz",
- "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==",
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true,
"license": "MIT"
},
- "node_modules/tldts-icann": {
- "version": "6.1.85",
- "resolved": "https://registry.npmjs.org/tldts-icann/-/tldts-icann-6.1.85.tgz",
- "integrity": "sha512-LIL8koGz5n2ni5wym7qw5vjeZxCgh5uI0Vs4LQu6M8k1IoknMttui/WTVI58jXBqRRSx76IniSJdeZDVFdALdw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tldts-core": "^6.1.85"
- }
- },
- "node_modules/toidentifier": {
+ "node_modules/tryer": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
+ "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
+ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/tslib": {
"version": "2.8.1",
@@ -3004,19 +2710,26 @@
"dev": true,
"license": "0BSD"
},
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
+ "prelude-ls": "~1.1.2"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.8.0"
}
},
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
@@ -3038,6 +2751,13 @@
"through": "^2.3.8"
}
},
+ "node_modules/underscore": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
+ "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
@@ -3058,38 +2778,32 @@
"node": ">=8"
}
},
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/urlpattern-polyfill": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
- "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==",
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true,
- "license": "MIT"
+ "license": "BSD-2-Clause"
},
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
}
},
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.8"
+ "node": ">=0.10.0"
}
},
"node_modules/wrap-ansi": {
@@ -3213,9 +2927,9 @@
}
},
"node_modules/zod": {
- "version": "3.23.8",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
- "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "version": "3.25.74",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.74.tgz",
+ "integrity": "sha512-J8poo92VuhKjNknViHRAIuuN6li/EwFbAC8OedzI8uxpEPGiXHGQu9wemIAioIpqgfB4SySaJhdk0mH5Y4ICBg==",
"dev": true,
"license": "MIT",
"funding": {
diff --git a/playwright.config.js b/playwright.config.js
index 5cba965..a420dc1 100644
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -6,23 +6,35 @@ const { defineConfig, devices } = require('@playwright/test');
*/
module.exports = defineConfig({
testDir: './tests',
- timeout: 30 * 1000,
+ /* Maximum time one test can run for. */
+ timeout: 60 * 1000,
expect: {
+ /**
+ * Maximum time expect() should wait for the condition to be met.
+ */
timeout: 5000
},
+ /* Run tests in files in parallel */
fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
-
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
+ /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
- trace: 'on-first-retry',
+ /* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:8080',
- screenshot: 'only-on-failure',
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
},
+ /* Configure projects for major browsers */
projects: [
{
name: 'chromium',
@@ -36,11 +48,21 @@ module.exports = defineConfig({
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
+ /* Test against mobile viewports. */
+ {
+ name: 'Mobile Chrome',
+ use: { ...devices['Pixel 5'] },
+ },
+ {
+ name: 'Mobile Safari',
+ use: { ...devices['iPhone 12'] },
+ },
],
+ /* Run local dev server before starting the tests */
webServer: {
command: 'node tests/serve.js',
- port: 8080,
- reuseExistingServer: true,
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
},
-});
\ No newline at end of file
+});
diff --git a/tests/accessibility.test.js b/tests/accessibility.test.js
index e8290b9..b98fe3b 100644
--- a/tests/accessibility.test.js
+++ b/tests/accessibility.test.js
@@ -1,222 +1,22 @@
-const { test, expect } = require('@playwright/test');
-const { AxeBuilder } = require('@axe-core/playwright');
+/**
+ * Main accessibility test runner
+ *
+ * This file is used by Jest to run the accessibility tests
+ */
-const PRODUCTION_URL = 'https://colinknapp.com';
-const LOCAL_URL = 'http://localhost:8080';
+const { execSync } = require('child_process');
+const path = require('path');
-const viewports = [
- { width: 375, height: 667, name: 'mobile' },
- { width: 1024, height: 768, name: 'desktop' }
-];
-
-async function getPageUrl(page) {
+describe('Accessibility Tests', () => {
+ test('Run accessibility tests', () => {
try {
- // Try production first
- await page.goto(PRODUCTION_URL, { timeout: 60000 });
- return PRODUCTION_URL;
+ // Run the accessibility tests
+ const scriptPath = path.join(__dirname, 'accessibility', 'run-accessibility-tests.sh');
+ execSync(`bash ${scriptPath}`, { stdio: 'inherit' });
} catch (error) {
- console.log('Production site not available, falling back to local');
- await page.goto(LOCAL_URL, { timeout: 60000 });
- return LOCAL_URL;
+ // If the tests fail, the script will exit with a non-zero code
+ // Jest will catch this and mark the test as failed
+ throw new Error('Accessibility tests failed');
}
-}
-
-viewports.forEach(viewport => {
- test.describe(`Accessibility Tests (${viewport.name})`, () => {
- test.beforeEach(async ({ page }) => {
- await page.setViewportSize(viewport);
- });
-
- test('should pass WCAG 2.1 Level AAA standards', async ({ page }) => {
- const url = await getPageUrl(page);
- console.log(`Running accessibility tests against ${url} on ${viewport.name}`);
-
- // Run axe accessibility tests
- const results = await new AxeBuilder({ page })
- .withTags(['wcag2a', 'wcag2aa', 'wcag2aaa'])
- .analyze();
-
- // Check for any violations
- expect(results.violations).toHaveLength(0);
- });
-
- test('should have proper ARIA attributes for theme toggle', async ({ page }) => {
- const url = await getPageUrl(page);
- console.log(`Running ARIA tests against ${url} on ${viewport.name}`);
-
- // Check theme toggle button
- const themeToggle = await page.locator('#themeToggle');
- expect(await themeToggle.getAttribute('aria-label')).toBe('Theme mode: Auto');
- expect(await themeToggle.getAttribute('role')).toBe('switch');
- expect(await themeToggle.getAttribute('aria-checked')).toBe('false');
- expect(await themeToggle.getAttribute('title')).toBe('Toggle between light, dark, and auto theme modes');
- expect(await themeToggle.getAttribute('tabindex')).toBe('0');
- });
-
- test('should have proper heading structure', async ({ page }) => {
- const url = await getPageUrl(page);
- console.log(`Running heading structure tests against ${url} on ${viewport.name}`);
-
- // Check main content area
- const mainContent = await page.locator('.container-fluid');
- expect(await mainContent.getAttribute('role')).toBe('main');
-
- // Check heading hierarchy
- const h1 = await page.locator('h1');
- expect(await h1.count()).toBe(1);
-
- const h2s = await page.locator('h2');
- expect(await h2s.count()).toBeGreaterThan(0);
- });
-
- test('should have working external links', async ({ page, request }) => {
- const url = await getPageUrl(page);
- console.log(`Running link validation tests against ${url} on ${viewport.name}`);
- await page.goto(url, { timeout: 60000 });
- await page.waitForLoadState('networkidle');
-
- // Get all external links
- const externalLinks = await page.$$('a[href^="http"]:not([href^="http://localhost"])');
-
- // Skip test if no external links found
- if (externalLinks.length === 0) {
- console.log('No external links found, skipping test');
- return;
- }
-
- // Set a longer timeout for external link checks
- test.setTimeout(120000);
-
- const brokenLinks = [];
- for (const link of externalLinks) {
- const href = await link.getAttribute('href');
- if (!href) continue;
-
- let attempts = 0;
- const maxAttempts = 3;
- let success = false;
- while (attempts < maxAttempts && !success) {
- attempts++;
- try {
- const response = await request.head(href, { timeout: 15000 });
- if (response.status() >= 400) {
- brokenLinks.push({
- href,
- status: response.status(),
- attempt: attempts
- });
- } else {
- success = true;
- }
- } catch (error) {
- if (attempts === maxAttempts) {
- brokenLinks.push({
- href,
- error: error.message,
- attempt: attempts
- });
- }
- // Wait before retrying
- await new Promise(resolve => setTimeout(resolve, 2000));
- }
- }
- }
-
- if (brokenLinks.length > 0) {
- console.log('\nBroken or inaccessible links:');
- brokenLinks.forEach(link => {
- if (link.error) {
- console.log(`- ${link.href}: ${link.error} (Attempt ${link.attempt}/${maxAttempts})`);
- } else {
- console.log(`- ${link.href}: HTTP ${link.status} (Attempt ${link.attempt}/${maxAttempts})`);
- }
- });
- throw new Error('Some external links are broken or inaccessible');
- }
- });
-
- test('should have proper color contrast', async ({ page }) => {
- const url = await getPageUrl(page);
- console.log(`Running color contrast tests against ${url} on ${viewport.name}`);
- await page.goto(url, { timeout: 60000 });
- await page.waitForLoadState('networkidle');
-
- // Check text color contrast in both light and dark modes
- const contrastInfo = await page.evaluate(() => {
- const getContrastRatio = (color1, color2) => {
- const getLuminance = (r, g, b) => {
- const [rs, gs, bs] = [r, g, b].map(c => {
- c = c / 255;
- return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
- });
- return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
- };
-
- const parseColor = (color) => {
- const rgb = color.match(/\d+/g).map(Number);
- return rgb.length === 3 ? rgb : [0, 0, 0];
- };
-
- const l1 = getLuminance(...parseColor(color1));
- const l2 = getLuminance(...parseColor(color2));
- const ratio = (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
- return ratio.toFixed(2);
- };
-
- const style = getComputedStyle(document.body);
- const textColor = style.color;
- const backgroundColor = style.backgroundColor;
- const contrastRatio = getContrastRatio(textColor, backgroundColor);
-
- return {
- textColor,
- backgroundColor,
- contrastRatio: parseFloat(contrastRatio)
- };
- });
-
- console.log('Color contrast information:', contrastInfo);
-
- // WCAG 2.1 Level AAA requires a contrast ratio of at least 7:1 for normal text
- expect(contrastInfo.contrastRatio).toBeGreaterThanOrEqual(7);
- });
-
- test('should have alt text for all images', async ({ page }) => {
- const url = await getPageUrl(page);
- console.log(`Running image alt text tests against ${url} on ${viewport.name}`);
- await page.goto(url, { timeout: 60000 });
- await page.waitForLoadState('networkidle');
-
- // Get all images
- const images = await page.$$('img');
-
- // Skip test if no images found
- if (images.length === 0) {
- console.log('No images found, skipping test');
- return;
- }
-
- const missingAlt = [];
- for (const img of images) {
- const alt = await img.getAttribute('alt');
- const src = await img.getAttribute('src');
-
- // Skip decorative images (empty alt is fine)
- const role = await img.getAttribute('role');
- if (role === 'presentation' || role === 'none') {
- continue;
- }
-
- if (!alt) {
- missingAlt.push(src);
- }
- }
-
- if (missingAlt.length > 0) {
- console.log('\nImages missing alt text:');
- missingAlt.forEach(src => console.log(`- ${src}`));
- throw new Error('Some images are missing alt text');
- }
- });
});
-});
\ No newline at end of file
+});
diff --git a/tests/accessibility/README.md b/tests/accessibility/README.md
index abee0c5..b5280d0 100644
--- a/tests/accessibility/README.md
+++ b/tests/accessibility/README.md
@@ -1,80 +1,64 @@
-# Accessibility Testing
+# Accessibility Testing Framework
-This directory contains tests for WCAG 2.1 AAA compliance.
+This directory contains tools and scripts for testing the website's accessibility compliance with WCAG 2.1 AAA standards.
## Overview
-The accessibility testing framework uses multiple tools to provide comprehensive coverage:
+The accessibility testing framework uses multiple approaches:
-1. **axe-core**: JavaScript library for automated accessibility testing
-2. **Pa11y**: Command-line tool for accessibility testing
-3. **Manual testing checklist**: For criteria that cannot be automatically tested
-
-## Requirements
-
-- Node.js and npm
-- Pa11y: `npm install -g pa11y`
-- axe-core: `npm install axe-core`
-- Playwright: `npm install playwright`
+1. **Automated Testing with Pa11y**: Command-line accessibility testing using Pa11y
+2. **Automated Testing with axe-core**: JavaScript-based accessibility testing using axe-core
+3. **Manual Testing Checklist**: A comprehensive checklist for aspects that can't be automated
## Running Tests
To run all accessibility tests:
```bash
-./run-accessibility-tests.sh [base-url]
+npm run test:accessibility
```
-Default base URL is `http://localhost:8080` if not specified.
+Or run directly:
-## Individual Test Scripts
+```bash
+./tests/accessibility/run-accessibility-tests.sh [BASE_URL]
+```
-- `axe-test.js`: Runs axe-core against all pages
-- `pa11y-test.sh`: Runs Pa11y against all pages
-- `manual-checklist.md`: Checklist for manual testing
+The default BASE_URL is `http://localhost:8080` if not specified.
-## WCAG 2.1 AAA Compliance
+## Test Components
-These tests check for WCAG 2.1 AAA compliance, which includes:
+### Pa11y Tests
-- **Perceivable**:
- - 7:1 contrast ratio for text
- - Text spacing customization
- - No loss of content when text is resized
- - Audio description for video
+Pa11y tests are run using the `pa11y-test.sh` script, which:
-- **Operable**:
- - No timing constraints
- - No interruptions
- - Multiple ways to find content
- - Proper heading structure
+- Tests multiple pages against WCAG 2.1 AAA standards
+- Generates JSON reports for each page
+- Creates a summary report
-- **Understandable**:
- - Unusual words are defined
- - Abbreviations are expanded
- - Reading level appropriate for audience
- - Context-sensitive help available
+### axe-core Tests
-- **Robust**:
- - Proper ARIA usage
- - Compatibility with assistive technologies
+axe-core tests are run using the `playwright-axe.js` script, which:
-## Test Reports
+- Uses Playwright to load pages
+- Injects axe-core into each page
+- Runs accessibility tests against WCAG 2.1 AAA standards
+- Generates detailed reports
-Reports are saved in the `../reports` directory:
+### Manual Testing
-- `axe-summary.json`: Summary of axe-core test results
-- `pa11y-summary.json`: Summary of Pa11y test results
-- `accessibility-summary.json`: Combined summary of all tests
+Some aspects of accessibility can't be automatically tested. The `manual-checklist.md` file provides a comprehensive checklist for manual testing, focusing on AAA-level criteria.
-## Manual Testing
+## Reports
-Some WCAG 2.1 AAA criteria require manual testing. Use the `manual-checklist.md` file to document these tests.
+Test reports are saved in the `tests/reports/` directory:
-## Additional Tools
+- Individual page reports (e.g., `pa11y-index.json`, `axe-index.json`)
+- Summary reports (`pa11y-summary.json`, `axe-summary.json`)
+- Combined accessibility report (`accessibility-summary.json`)
-For more comprehensive testing, consider using:
+## Requirements
-- **Accessibility Insights for Web**: Browser extension for detailed accessibility testing
-- **NVDA or VoiceOver**: Screen readers for testing screen reader compatibility
-- **Keyboard-only navigation**: Test all functionality without using a mouse
+- Node.js
+- NPM packages: pa11y, axe-core, playwright
+- For Pa11y: `npm install -g pa11y` or use npx
diff --git a/tests/accessibility/generate-detailed-report.js b/tests/accessibility/generate-detailed-report.js
new file mode 100644
index 0000000..9644ef2
--- /dev/null
+++ b/tests/accessibility/generate-detailed-report.js
@@ -0,0 +1,537 @@
+/**
+ * Generate a detailed accessibility report for WCAG 2.1 AAA compliance
+ *
+ * This script analyzes all pages and generates a comprehensive report
+ * of accessibility issues that need to be fixed for AAA compliance
+ */
+
+const { chromium } = require('playwright');
+const fs = require('fs');
+const path = require('path');
+const axeCore = require('axe-core');
+
+// URLs to test - expand this list to cover all pages
+const BASE_URL = process.argv[2] || 'http://localhost:8080'\;
+const PAGES = [
+ '/',
+ '/stories/',
+ '/stories/open-source-success.html',
+ '/stories/viperwire.html',
+ '/stories/airport-dns.html',
+ '/stories/wordpress-security.html',
+ '/stories/nitric-leadership.html',
+ '/stories/healthcare-platform.html',
+ '/stories/web-design-java.html',
+ '/stories/motherboard-repair.html',
+ '/stories/fawe-plotsquared.html',
+ '/stories/showerloop.html',
+ '/stories/athion-turnaround.html',
+ '/stories/youtube-game-dev.html',
+ '/stories/app-development.html',
+ '/one-pager-tools/csv-tool.html'
+];
+
+// Create reports directory if it doesn't exist
+const reportsDir = path.join(__dirname, '../reports');
+if (!fs.existsSync(reportsDir)) {
+ fs.mkdirSync(reportsDir, { recursive: true });
+}
+
+// Issues storage
+const allIssues = {
+ byPage: {},
+ byRule: {},
+ summary: {
+ totalPages: 0,
+ pagesWithIssues: 0,
+ totalIssues: 0,
+ issuesByImpact: {
+ critical: 0,
+ serious: 0,
+ moderate: 0,
+ minor: 0
+ }
+ }
+};
+
+async function runAxe(page, pageUrl) {
+ try {
+ // Use a file URL to load axe-core from a local file to avoid CSP issues
+ const axeScriptPath = path.join(__dirname, 'axe-core.js');
+ fs.writeFileSync(axeScriptPath, axeCore.source);
+
+ // Add the script as a file
+ await page.addScriptTag({ path: axeScriptPath });
+
+ // Run axe with WCAG 2.1 AAA rules
+ const results = await page.evaluate(() => {
+ return new Promise(resolve => {
+ axe.run(document, {
+ runOnly: {
+ type: 'tag',
+ values: ['wcag2aaa']
+ },
+ resultTypes: ['violations', 'incomplete'],
+ rules: {
+ 'color-contrast': { enabled: true, options: { noScroll: true } }
+ }
+ })
+ .then(results => resolve(results))
+ .catch(err => resolve({ error: err.toString() }));
+ });
+ });
+
+ // Clean up temporary file
+ fs.unlinkSync(axeScriptPath);
+
+ return results;
+ } catch (error) {
+ console.error('Error running axe:', error);
+ return { error: error.toString() };
+ }
+}
+
+async function testPage(browser, pageUrl) {
+ const context = await browser.newContext({
+ bypassCSP: true
+ });
+ const page = await context.newPage();
+ console.log(`Testing ${pageUrl}...`);
+
+ try {
+ // Navigate to the page
+ await page.goto(pageUrl, { waitUntil: 'networkidle' });
+
+ // Run axe-core tests
+ const results = await runAxe(page, pageUrl);
+
+ // Save results to file
+ const fileName = pageUrl === BASE_URL ? 'index' : pageUrl.replace(BASE_URL, '').replace(/\//g, '-').replace(/^-/, '');
+ const reportPath = path.join(reportsDir, `axe-${fileName || 'index'}.json`);
+ fs.writeFileSync(reportPath, JSON.stringify(results, null, 2));
+
+ // Log results summary
+ if (results.error) {
+ console.error(`Error running axe-core on ${pageUrl}:`, results.error);
+ return { url: pageUrl, success: false, error: results.error };
+ }
+
+ const { violations, incomplete } = results;
+ console.log(`Results for ${pageUrl}:`);
+ console.log(`- Violations: ${violations.length}`);
+ console.log(`- Incomplete: ${incomplete.length}`);
+
+ // Track issues for detailed report
+ const pageIssues = [];
+
+ // Process violations
+ if (violations.length > 0) {
+ console.log('\nViolations:');
+ violations.forEach((violation, i) => {
+ console.log(`${i + 1}. ${violation.id} - ${violation.help} (Impact: ${violation.impact})`);
+ console.log(` ${violation.description}`);
+ console.log(` WCAG: ${violation.tags.filter(t => t.startsWith('wcag')).join(', ')}`);
+ console.log(` Elements: ${violation.nodes.length}`);
+
+ // Add to issues tracking
+ violation.nodes.forEach(node => {
+ const issue = {
+ rule: violation.id,
+ impact: violation.impact,
+ description: violation.description,
+ help: violation.help,
+ helpUrl: violation.helpUrl,
+ wcagTags: violation.tags.filter(t => t.startsWith('wcag')),
+ element: node.html,
+ target: node.target,
+ failureSummary: node.failureSummary,
+ elementData: node.any.map(d => d.data || {})
+ };
+ pageIssues.push(issue);
+
+ // Update rule-based tracking
+ if (!allIssues.byRule[violation.id]) {
+ allIssues.byRule[violation.id] = {
+ id: violation.id,
+ description: violation.description,
+ help: violation.help,
+ helpUrl: violation.helpUrl,
+ impact: violation.impact,
+ wcagTags: violation.tags.filter(t => t.startsWith('wcag')),
+ occurrences: []
+ };
+ }
+
+ allIssues.byRule[violation.id].occurrences.push({
+ page: pageUrl,
+ element: node.html,
+ target: node.target,
+ failureSummary: node.failureSummary,
+ elementData: node.any.map(d => d.data || {})
+ });
+
+ // Update summary stats
+ allIssues.summary.totalIssues++;
+ if (violation.impact) {
+ allIssues.summary.issuesByImpact[violation.impact]++;
+ }
+ });
+ });
+ }
+
+ // Store page issues
+ allIssues.byPage[pageUrl] = {
+ url: pageUrl,
+ issueCount: pageIssues.length,
+ issues: pageIssues
+ };
+
+ // Update summary
+ allIssues.summary.totalPages++;
+ if (pageIssues.length > 0) {
+ allIssues.summary.pagesWithIssues++;
+ }
+
+ return {
+ url: pageUrl,
+ success: violations.length === 0,
+ violations: violations.length,
+ incomplete: incomplete.length
+ };
+ } catch (error) {
+ console.error(`Error testing ${pageUrl}:`, error);
+ return { url: pageUrl, success: false, error: error.toString() };
+ } finally {
+ await page.close();
+ await context.close();
+ }
+}
+
+function generateFixRecommendations() {
+ const recommendations = {};
+
+ // Process color contrast issues
+ if (allIssues.byRule['color-contrast-enhanced']) {
+ const colorIssues = allIssues.byRule['color-contrast-enhanced'];
+ recommendations.colorContrast = {
+ title: 'Color Contrast Issues',
+ description: 'The following color combinations need to be updated to meet WCAG 2.1 AAA requirements (7:1 contrast ratio):',
+ colorPairs: []
+ };
+
+ // Group by color pairs
+ const colorPairMap = {};
+ colorIssues.occurrences.forEach(occurrence => {
+ occurrence.elementData.forEach(data => {
+ if (data.fgColor && data.bgColor) {
+ const key = `${data.fgColor}/${data.bgColor}`;
+ if (!colorPairMap[key]) {
+ colorPairMap[key] = {
+ fgColor: data.fgColor,
+ bgColor: data.bgColor,
+ contrastRatio: data.contrastRatio,
+ requiredRatio: data.expectedContrastRatio,
+ pages: new Set(),
+ elements: []
+ };
+ }
+ colorPairMap[key].pages.add(occurrence.page);
+ colorPairMap[key].elements.push({
+ html: occurrence.element,
+ page: occurrence.page
+ });
+ }
+ });
+ });
+
+ // Convert to array and add suggestions
+ Object.values(colorPairMap).forEach(pair => {
+ const suggestion = {
+ foreground: pair.fgColor,
+ background: pair.bgColor,
+ currentRatio: pair.contrastRatio,
+ requiredRatio: pair.requiredRatio,
+ pagesAffected: Array.from(pair.pages),
+ elementCount: pair.elements.length,
+ suggestedFixes: []
+ };
+
+ // Generate suggested fixes
+ // Make foreground darker
+ const darkerFg = darkenColor(pair.fgColor, 0.2);
+ suggestion.suggestedFixes.push({
+ type: 'Darken foreground',
+ color: darkerFg,
+ description: `Change foreground color from ${pair.fgColor} to ${darkerFg}`
+ });
+
+ // Make background lighter
+ const lighterBg = lightenColor(pair.bgColor, 0.2);
+ suggestion.suggestedFixes.push({
+ type: 'Lighten background',
+ color: lighterBg,
+ description: `Change background color from ${pair.bgColor} to ${lighterBg}`
+ });
+
+ recommendations.colorContrast.colorPairs.push(suggestion);
+ });
+ }
+
+ return recommendations;
+}
+
+// Helper function to darken a hex color
+function darkenColor(hex, amount) {
+ return adjustColor(hex, -amount);
+}
+
+// Helper function to lighten a hex color
+function lightenColor(hex, amount) {
+ return adjustColor(hex, amount);
+}
+
+// Helper function to adjust a hex color
+function adjustColor(hex, amount) {
+ let r = parseInt(hex.substring(1, 3), 16);
+ let g = parseInt(hex.substring(3, 5), 16);
+ let b = parseInt(hex.substring(5, 7), 16);
+
+ if (amount > 0) {
+ // Lighten
+ r = Math.min(255, Math.round(r + (255 - r) * amount));
+ g = Math.min(255, Math.round(g + (255 - g) * amount));
+ b = Math.min(255, Math.round(b + (255 - b) * amount));
+ } else {
+ // Darken
+ amount = -amount;
+ r = Math.max(0, Math.round(r * (1 - amount)));
+ g = Math.max(0, Math.round(g * (1 - amount)));
+ b = Math.max(0, Math.round(b * (1 - amount)));
+ }
+
+ return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
+}
+
+async function runTests() {
+ const browser = await chromium.launch();
+ const results = [];
+
+ try {
+ // Test each page
+ for (const pagePath of PAGES) {
+ const pageUrl = `${BASE_URL}${pagePath}`;
+ const result = await testPage(browser, pageUrl);
+ results.push(result);
+ }
+
+ // Generate detailed report
+ const recommendations = generateFixRecommendations();
+
+ const detailedReport = {
+ timestamp: new Date().toISOString(),
+ baseUrl: BASE_URL,
+ summary: allIssues.summary,
+ recommendations: recommendations,
+ issuesByRule: allIssues.byRule
+ };
+
+ // Save detailed report
+ fs.writeFileSync(
+ path.join(reportsDir, 'accessibility-detailed-report.json'),
+ JSON.stringify(detailedReport, null, 2)
+ );
+
+ // Generate HTML report
+ const htmlReport = generateHtmlReport(detailedReport);
+ fs.writeFileSync(
+ path.join(reportsDir, 'accessibility-report.html'),
+ htmlReport
+ );
+
+ console.log('\n=== Detailed Report Generated ===');
+ console.log(`Total pages tested: ${detailedReport.summary.totalPages}`);
+ console.log(`Pages with issues: ${detailedReport.summary.pagesWithIssues}`);
+ console.log(`Total issues found: ${detailedReport.summary.totalIssues}`);
+ console.log(`Issues by impact:`);
+ Object.entries(detailedReport.summary.issuesByImpact).forEach(([impact, count]) => {
+ if (count > 0) {
+ console.log(` - ${impact}: ${count}`);
+ }
+ });
+ console.log(`\nDetailed report saved to: ${path.join(reportsDir, 'accessibility-detailed-report.json')}`);
+ console.log(`HTML report saved to: ${path.join(reportsDir, 'accessibility-report.html')}`);
+
+ // Exit with appropriate code
+ process.exit(detailedReport.summary.totalIssues > 0 ? 1 : 0);
+ } catch (error) {
+ console.error('Error running tests:', error);
+ process.exit(1);
+ } finally {
+ await browser.close();
+ }
+}
+
+function generateHtmlReport(report) {
+ const colorPairs = report.recommendations.colorContrast ? report.recommendations.colorContrast.colorPairs : [];
+
+ return `
+
+
+
+
+ Accessibility Report - WCAG 2.1 AAA Compliance
+ Summary
+
+ ${report.summary.issuesByImpact.critical > 0 ? `
+ Color Contrast Issues
+ ${colorPairs.length === 0 ? 'Color Combination
+
+ ${pair.pagesAffected.map(page => `
+ Suggested Fixes
+ ${pair.suggestedFixes.map(fix => `
+ ${fix.type}
+
+ Issues by Rule
+
+
+
+
+`;
+}
+
+runTests();
diff --git a/tests/accessibility/generate-report.js b/tests/accessibility/generate-report.js
new file mode 100644
index 0000000..f273fb4
--- /dev/null
+++ b/tests/accessibility/generate-report.js
@@ -0,0 +1,212 @@
+/**
+ * Generate a comprehensive accessibility report
+ * This script analyzes the axe-core and Pa11y test results and generates a report
+ * of all accessibility issues that need to be fixed
+ */
+
+const fs = require('fs');
+const path = require('path');
+
+// Directory containing test reports
+const reportsDir = path.join(__dirname, '../reports');
+
+// Output report file
+const outputFile = path.join(reportsDir, 'accessibility-issues.md');
+
+// Get all axe-core report files
+const axeReports = fs.readdirSync(reportsDir)
+ .filter(file => file.startsWith('axe-') && file.endsWith('.json'))
+ .map(file => {
+ try {
+ const content = fs.readFileSync(path.join(reportsDir, file), 'utf8');
+ return { file, content: JSON.parse(content) };
+ } catch (error) {
+ console.error(`Error reading ${file}:`, error.message);
+ return { file, content: null };
+ }
+ })
+ .filter(report => report.content !== null);
+
+// Get all Pa11y report files
+const pa11yReports = fs.readdirSync(reportsDir)
+ .filter(file => file.startsWith('pa11y') && file.endsWith('.json') && !file.includes('summary'))
+ .map(file => {
+ try {
+ const content = fs.readFileSync(path.join(reportsDir, file), 'utf8');
+ return { file, content: JSON.parse(content) };
+ } catch (error) {
+ console.error(`Error reading ${file}:`, error.message);
+ return { file, content: null };
+ }
+ })
+ .filter(report => report.content !== null);
+
+// Generate report
+let report = `# Accessibility Issues Report
+Generated on: ${new Date().toISOString()}
+
+This report lists all accessibility issues found by automated testing tools.
+Fixing these issues will help achieve WCAG 2.1 AAA compliance.
+
+## Summary
+
+`;
+
+// Process axe-core reports
+const axeIssues = [];
+axeReports.forEach(report => {
+ if (report.content && report.content.violations) {
+ report.content.violations.forEach(violation => {
+ violation.nodes.forEach(node => {
+ axeIssues.push({
+ page: report.file.replace('axe-', '').replace('.json', ''),
+ id: violation.id,
+ impact: violation.impact,
+ description: violation.description,
+ help: violation.help,
+ helpUrl: violation.helpUrl,
+ element: node.html || node.target?.join(', ') || 'Unknown element',
+ wcag: violation.tags.filter(t => t.startsWith('wcag')).join(', ')
+ });
+ });
+ });
+ }
+});
+
+// Process Pa11y reports
+const pa11yIssues = [];
+pa11yReports.forEach(report => {
+ if (report.content && report.content.issues) {
+ report.content.issues.forEach(issue => {
+ pa11yIssues.push({
+ page: report.file.replace('pa11y', '').replace('.json', ''),
+ code: issue.code,
+ type: issue.type,
+ message: issue.message,
+ context: issue.context,
+ selector: issue.selector
+ });
+ });
+ }
+});
+
+// Add summary counts to report
+report += `- Total pages tested: ${axeReports.length}
+- Pages with axe-core issues: ${axeReports.filter(r => r.content?.violations?.length > 0).length}
+- Total axe-core issues: ${axeIssues.length}
+- Pages with Pa11y issues: ${pa11yReports.filter(r => r.content?.issues?.length > 0).length}
+- Total Pa11y issues: ${pa11yIssues.length}
+
+## Common Issues
+
+`;
+
+// Group issues by type
+const issuesByType = {};
+axeIssues.forEach(issue => {
+ if (!issuesByType[issue.id]) {
+ issuesByType[issue.id] = {
+ count: 0,
+ description: issue.description,
+ help: issue.help,
+ helpUrl: issue.helpUrl,
+ wcag: issue.wcag,
+ pages: new Set()
+ };
+ }
+ issuesByType[issue.id].count++;
+ issuesByType[issue.id].pages.add(issue.page);
+});
+
+// Sort issues by count
+const sortedIssues = Object.entries(issuesByType)
+ .sort((a, b) => b[1].count - a[1].count);
+
+// Add common issues to report
+sortedIssues.forEach(([id, info]) => {
+ report += `### ${id} (${info.count} occurrences)
+
+- **Description**: ${info.description}
+- **Help**: ${info.help}
+- **WCAG**: ${info.wcag}
+- **Pages affected**: ${Array.from(info.pages).join(', ')}
+- **More info**: ${info.helpUrl}
+
+`;
+});
+
+// Add detailed issues by page
+report += `## Issues by Page
+
+`;
+
+// Group issues by page
+const issuesByPage = {};
+axeIssues.forEach(issue => {
+ if (!issuesByPage[issue.page]) {
+ issuesByPage[issue.page] = [];
+ }
+ issuesByPage[issue.page].push(issue);
+});
+
+// Add page-specific issues to report
+Object.entries(issuesByPage).forEach(([page, issues]) => {
+ report += `### ${page}
+
+`;
+ issues.forEach(issue => {
+ report += `- **${issue.id}** (${issue.impact}): ${issue.help}
+ - Element: \`${issue.element.substring(0, 100)}${issue.element.length > 100 ? '...' : ''}\`
+ - WCAG: ${issue.wcag}
+
+`;
+ });
+});
+
+// Add recommended fixes
+report += `## Recommended Fixes
+
+Based on the issues found, here are the recommended fixes:
+
+`;
+
+// Add specific recommendations for common issues
+if (issuesByType['color-contrast-enhanced']) {
+ report += `### Color Contrast Issues
+
+1. Update link colors to meet 7:1 contrast ratio:
+ - Current blue link color (#0056b3) on light background (#f5f5f5) has 6.45:1 ratio
+ - Recommended: Change to darker blue (#004494) for 7:1+ ratio
+
+2. Update CSS in the following files:
+ - \`docker/resume/styles.css\`: Update link colors
+ - \`docker/resume/stories/stories.css\`: Update story-specific link colors
+
+`;
+}
+
+// Add implementation plan
+report += `## Implementation Plan
+
+1. Fix color contrast issues first (highest impact)
+2. Address any document structure issues
+3. Fix remaining issues by priority (serious > moderate > minor)
+4. Re-run tests to verify fixes
+
+## Testing Instructions
+
+To test accessibility compliance:
+
+\`\`\`bash
+# Run all accessibility tests
+npm run test:accessibility
+
+# Generate updated report
+node tests/accessibility/generate-report.js
+\`\`\`
+
+`;
+
+// Write report to file
+fs.writeFileSync(outputFile, report);
+console.log(`Accessibility issues report generated at: ${outputFile}`);
diff --git a/tests/accessibility/manual-checklist.md b/tests/accessibility/manual-checklist.md
index 64ce073..53a9b48 100644
--- a/tests/accessibility/manual-checklist.md
+++ b/tests/accessibility/manual-checklist.md
@@ -1,99 +1,119 @@
-# WCAG 2.1 AAA Manual Testing Checklist
+# Manual Accessibility Testing Checklist
-This checklist covers WCAG 2.1 AAA criteria that require manual testing and cannot be fully automated.
+This checklist covers aspects of WCAG 2.1 AAA compliance that cannot be fully automated and require manual verification.
## Instructions
-For each item, mark it as:
-- ✅ Pass
-- ❌ Fail
-- N/A Not Applicable
+1. For each page in the site, go through this checklist
+2. Mark each item as:
+ - ✅ Pass
+ - ❌ Fail
+ - N/A Not applicable
+3. For any failures, note the specific issue and location
-## Text Spacing (1.4.12 AAA)
+## Pages to Test
-- [ ] Text can be displayed with:
- - Line height of at least 1.5 times the font size
- - Spacing after paragraphs of at least 2 times the font size
- - Letter spacing of at least 0.12 times the font size
- - Word spacing of at least 0.16 times the font size
+- Home page (/)
+- Stories index (/stories/)
+- Individual story pages (e.g., /stories/open-source-success.html)
+- Tools pages (e.g., /one-pager-tools/csv-tool.html)
-## No Timing (2.2.3 AAA)
+## Checklist
-- [ ] Timing is not an essential part of the activity presented by the content
-- [ ] No time limits or constraints on user interaction
+### Perceivable
-## Interruptions (2.2.4 AAA)
+#### 1.2.6 Sign Language (AAA)
+- [ ] Sign language interpretation is provided for all prerecorded audio content in synchronized media
+#### 1.2.7 Extended Audio Description (AAA)
+- [ ] Extended audio description is provided for all prerecorded video content
+
+#### 1.2.8 Media Alternative (AAA)
+- [ ] Alternative for time-based media is provided for all prerecorded synchronized media and for all prerecorded video-only media
+
+#### 1.2.9 Audio-only (Live) (AAA)
+- [ ] Alternative for time-based media that presents equivalent information for live audio-only content is provided
+
+#### 1.3.6 Identify Purpose (AAA)
+- [ ] The purpose of UI components, icons, and regions can be programmatically determined
+
+#### 1.4.6 Contrast (Enhanced) (AAA)
+- [ ] Visual presentation of text and images of text has a contrast ratio of at least 7:1
+- [ ] Large text (over 18pt or 14pt bold) has a contrast ratio of at least 4.5:1
+
+#### 1.4.9 Images of Text (No Exception) (AAA)
+- [ ] Images of text are only used for pure decoration or where a particular presentation of text is essential to the information being conveyed
+
+### Operable
+
+#### 2.1.3 Keyboard (No Exception) (AAA)
+- [ ] All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes
+
+#### 2.2.3 No Timing (AAA)
+- [ ] Timing is not an essential part of the event or activity presented by the content
+
+#### 2.2.4 Interruptions (AAA)
- [ ] Interruptions can be postponed or suppressed by the user
-- [ ] No unexpected popups or modal dialogs
-
-## Re-authenticating (2.2.5 AAA)
+#### 2.2.5 Re-authenticating (AAA)
- [ ] When an authenticated session expires, the user can continue the activity without loss of data after re-authenticating
-## Three Flashes (2.3.2 AAA)
+#### 2.2.6 Timeouts (AAA)
+- [ ] Users are warned of the duration of any user inactivity that could cause data loss
+#### 2.3.2 Three Flashes (AAA)
- [ ] Web pages do not contain anything that flashes more than three times in any one second period
-## Location (2.4.8 AAA)
+#### 2.3.3 Animation from Interactions (AAA)
+- [ ] Motion animation triggered by interaction can be disabled
+#### 2.4.8 Location (AAA)
- [ ] Information about the user's location within a set of web pages is available
-## Link Purpose (2.4.9 AAA)
-
+#### 2.4.9 Link Purpose (Link Only) (AAA)
- [ ] A mechanism is available to allow the purpose of each link to be identified from link text alone
-## Section Headings (2.4.10 AAA)
-
+#### 2.4.10 Section Headings (AAA)
- [ ] Section headings are used to organize the content
-- [ ] Headings follow a logical hierarchy (h1, h2, h3, etc.)
-## Unusual Words (3.1.3 AAA)
+#### 2.5.5 Target Size (AAA)
+- [ ] The size of the target for pointer inputs is at least 44 by 44 CSS pixels
+#### 2.5.6 Concurrent Input Mechanisms (AAA)
+- [ ] Web content does not restrict use of input modalities available on a platform
+
+### Understandable
+
+#### 3.1.3 Unusual Words (AAA)
- [ ] A mechanism is available for identifying specific definitions of words or phrases used in an unusual or restricted way
-## Abbreviations (3.1.4 AAA)
-
+#### 3.1.4 Abbreviations (AAA)
- [ ] A mechanism for identifying the expanded form or meaning of abbreviations is available
-## Reading Level (3.1.5 AAA)
-
-- [ ] Content does not require reading ability more advanced than the lower secondary education level
-- [ ] Supplemental content is available for more complex text
-
-## Pronunciation (3.1.6 AAA)
+#### 3.1.5 Reading Level (AAA)
+- [ ] When text requires reading ability more advanced than the lower secondary education level, supplemental content is available
+#### 3.1.6 Pronunciation (AAA)
- [ ] A mechanism is available for identifying specific pronunciation of words where meaning is ambiguous without knowing the pronunciation
-## Error Prevention (3.3.6 AAA)
-
-- [ ] For submissions that cause legal commitments or financial transactions:
- - Submissions are reversible
- - Data entered is checked for errors
- - User can review and confirm before final submission
-
-## Help (3.3.5 AAA)
+#### 3.2.5 Change on Request (AAA)
+- [ ] Changes of context are initiated only by user request or a mechanism is available to turn off such changes
+#### 3.3.5 Help (AAA)
- [ ] Context-sensitive help is available
-## Screen Reader Testing
+#### 3.3.6 Error Prevention (All) (AAA)
+- [ ] For web pages that require the user to submit information, at least one of the following is true:
+ - Submissions are reversible
+ - Data entered by the user is checked for input errors and the user is provided an opportunity to correct them
+ - A mechanism is available for reviewing, confirming, and correcting information before finalizing the submission
-- [ ] Test with at least one screen reader (e.g., NVDA, VoiceOver)
-- [ ] All content can be accessed and understood through screen reader
-- [ ] Interactive elements are properly announced
-- [ ] Form controls have proper labels and instructions
+## Notes and Issues
-## User Testing
-
-- [ ] Testing with users with disabilities has been conducted
-- [ ] Feedback has been incorporated into the website
-
-## Notes and Observations
-
-(Add any notes or observations here)
+
## Tester Information
-- Tester Name:
-- Date:
-- Browser/Assistive Technology Used:
+- Name:
+- Date:
+- Browser/assistive technology used:
diff --git a/tests/accessibility/pa11y-test.sh b/tests/accessibility/pa11y-test.sh
index 02419df..7062c2e 100755
--- a/tests/accessibility/pa11y-test.sh
+++ b/tests/accessibility/pa11y-test.sh
@@ -1,9 +1,8 @@
#!/bin/bash
# =====================================================================
-# pa11y-test.sh - Test for WCAG 2.1 AAA compliance using Pa11y
+# pa11y-test.sh - Run Pa11y accessibility tests
# =====================================================================
-# This script runs Pa11y against all pages of the website to check for
-# WCAG 2.1 AAA compliance.
+# This script runs Pa11y accessibility tests for WCAG 2.1 AAA compliance
# =====================================================================
set -e
@@ -15,98 +14,87 @@ else
BASE_URL="$1"
fi
-# Create reports directory if it doesn't exist
-REPORTS_DIR="$(dirname "$0")/../reports"
+TESTS_DIR="$(dirname "$0")"
+REPORTS_DIR="$TESTS_DIR/../reports"
mkdir -p "$REPORTS_DIR"
-# List of pages to test
-PAGES=(
- "/"
- "/stories/"
- "/stories/open-source-success.html"
- "/stories/viperwire.html"
- "/one-pager-tools/csv-tool.html"
-)
-
echo "=== Testing WCAG 2.1 AAA Compliance with Pa11y ==="
echo "Using base URL: $BASE_URL"
-# Function to run Pa11y on a single page
-run_pa11y() {
- local page="$1"
- local url="${BASE_URL}${page}"
- local filename=$(echo "$page" | sed 's/\//-/g' | sed 's/^-//' | sed 's/-$//')
+# Get URLs from sitemap
+SITEMAP_URL="$BASE_URL/sitemap.xml"
+echo "Fetching pages from sitemap: $SITEMAP_URL"
+URLS=($(curl -s "$SITEMAP_URL" | grep -o '
+
+
+
+ ${Object.values(report.issuesByRule).map(rule => `
+ Rule
+ Impact
+ Description
+ Occurrences
+ WCAG Criteria
+
+
+ `).join('')}
+
+ ${rule.id}
+ ${rule.impact}
+ ${rule.description}
+ ${rule.occurrences.length}
+ ${rule.wcagTags.join(', ')}
+