diff --git a/ads/README.md b/ads/README.md index 84fea4909283..abb0d980d24f 100644 --- a/ads/README.md +++ b/ads/README.md @@ -13,26 +13,26 @@ This guide provides details for ad networks to create an `amp-ad` integration fo -- [Overview](#overview) -- [Constraints](#constraints) -- [The iframe sandbox](#the-iframe-sandbox) - - [Available information to the ad](#available-information-to-the-ad) - - [Available APIs](#available-apis) - - [Exceptions to available APIs and information](#exceptions-to-available-apis-and-information) - - [Ad viewability](#ad-viewability) - - [Ad resizing](#ad-resizing) - - [Support for multi-size ad requests](#support-for-multi-size-ad-requests) - - [amp-consent integration](#amp-consent-integration) - - [Optimizing ad performance](#optimizing-ad-performance) - - [Ad markup](#ad-markup) - - [1st party cookies](#1st-party-cookies) -- [Developer guidelines for a pull request](#developer-guidelines-for-a-pull-request) - - [Files to change](#files-to-change) - - [Verify your examples](#verify-your-examples) - - [Tests](#tests) - - [Lint and type-check](#lint-and-type-check) - - [Other tips](#other-tips) -- [Developer announcements for ads related API changes](#developer-announcements-for-ads-related-api-changes) +- [Overview](#overview) +- [Constraints](#constraints) +- [The iframe sandbox](#the-iframe-sandbox) + - [Available information to the ad](#available-information-to-the-ad) + - [Available APIs](#available-apis) + - [Exceptions to available APIs and information](#exceptions-to-available-apis-and-information) + - [Ad viewability](#ad-viewability) + - [Ad resizing](#ad-resizing) + - [Support for multi-size ad requests](#support-for-multi-size-ad-requests) + - [amp-consent integration](#amp-consent-integration) + - [Optimizing ad performance](#optimizing-ad-performance) + - [Ad markup](#ad-markup) + - [1st party cookies](#1st-party-cookies) +- [Developer guidelines for a pull request](#developer-guidelines-for-a-pull-request) + - [Files to change](#files-to-change) + - [Verify your examples](#verify-your-examples) + - [Tests](#tests) + - [Lint and type-check](#lint-and-type-check) + - [Other tips](#other-tips) +- [Developer announcements for ads related API changes](#developer-announcements-for-ads-related-api-changes) ## Overview @@ -44,15 +44,15 @@ If you are an ad technology provider looking to integrate with AMP HTML, please Below is a summary of constraints placed on external resources, such as ads in AMP HTML: -- Because AMP pages are served on HTTPS and ads cannot be proxied, ads must be served over HTTPS. -- The size of an ad unit must be static. It must be knowable without fetching the ad and it cannot change at runtime except through [iframe resizing](#ad-resizing). -- If placing the ad requires running JavaScript (assumed to be true for 100% of ads served through networks), the ad must be placed on an origin different from the AMP document itself. Reasons include: - - Improved security. - - Takes synchronous HTTP requests made by the ad out of the critical rendering path of the primary page. - - Allows browsers to run the ad in a different process from the primary page (even better security and prevents JS inside the ad to block the main page UI thread). - - Prevents ads doing less than optimal things to measure user behavior and other interference with the primary page. -- The AMP Runtime may at any moment decide that there are too many iframes on a page and that memory is low. In that case, the AMP Runtime unloads ads that were previously loaded and are no longer visible. It may later load new ads in the same slot if the user scrolls them back into view. -- The AMP Runtime may decide to set an ad that is currently not visible to `display: none` to reduce browser layout and compositing cost. +- Because AMP pages are served on HTTPS and ads cannot be proxied, ads must be served over HTTPS. +- The size of an ad unit must be static. It must be knowable without fetching the ad and it cannot change at runtime except through [iframe resizing](#ad-resizing). +- If placing the ad requires running JavaScript (assumed to be true for 100% of ads served through networks), the ad must be placed on an origin different from the AMP document itself. Reasons include: + - Improved security. + - Takes synchronous HTTP requests made by the ad out of the critical rendering path of the primary page. + - Allows browsers to run the ad in a different process from the primary page (even better security and prevents JS inside the ad to block the main page UI thread). + - Prevents ads doing less than optimal things to measure user behavior and other interference with the primary page. +- The AMP Runtime may at any moment decide that there are too many iframes on a page and that memory is low. In that case, the AMP Runtime unloads ads that were previously loaded and are no longer visible. It may later load new ads in the same slot if the user scrolls them back into view. +- The AMP Runtime may decide to set an ad that is currently not visible to `display: none` to reduce browser layout and compositing cost. ## The iframe sandbox @@ -199,9 +199,9 @@ window.context Here are some factors that affect whether the resize will be executed: -- Whether the resize is triggered by the user action; -- Whether the resize is requested for a currently active ad; -- Whether the resize is requested for an ad below the viewport or above the viewport. +- Whether the resize is triggered by the user action; +- Whether the resize is requested for a currently active ad; +- Whether the resize is requested for an ad below the viewport or above the viewport. #### Specifying an overflow element @@ -343,12 +343,12 @@ Please read through [developing.md](../docs/developing.md) before contributing t If you're adding support for a new third-party ad service, changes to the following files are expected: -- `/ads/yournetwork.js`: Implement the main logic here. This is the code that's invoked in the third-party iframe once loaded. -- `/ads/yournetwork.md`: Documentation detailing yourr ad service for publishers to read. -- `/ads/_config.js`: Add service specific configuration here. -- `/3p/vendors/yournetwork.js`: Register your service here. -- `/extensions/amp-ad/amp-ad.md`: Add a link that points to your publisher doc. -- `/examples/ads.amp.html`: Add publisher examples here. Since a real ad isn't guaranteed to fill, a consistently displayed fake ad is highly recommended here to help AMP developers confidently identify new bugs. +- `/ads/yournetwork.js`: Implement the main logic here. This is the code that's invoked in the third-party iframe once loaded. +- `/ads/yournetwork.md`: Documentation detailing yourr ad service for publishers to read. +- `/ads/_config.js`: Add service specific configuration here. +- `/3p/vendors/yournetwork.js`: Register your service here. +- `/extensions/amp-ad/amp-ad.md`: Add a link that points to your publisher doc. +- `/examples/ads.amp.html`: Add publisher examples here. Since a real ad isn't guaranteed to fill, a consistently displayed fake ad is highly recommended here to help AMP developers confidently identify new bugs. ### Verify your examples @@ -379,10 +379,10 @@ To speed up the review process, please run `amp lint` and `amp check-types`, the ### Other tips -- Add **cc ampproject/wg-monetization** in all pull request's descriptions. -- It's highly recommended to maintain [an integration test outside AMP repo](../3p/README.md#adding-proper-integration-tests). -- Please consider implementing the `render-start` and `no-content-available` APIs (see [Available APIs](#available-apis)), which helps AMP to provide user a much better ad loading experience. -- [CLA](../docs/contributing.md#contributing-code): for anyone who has trouble to pass the automatic CLA check in a pull request, try to follow the guidelines provided by the CLA Bot. Common mistakes are: +- Add **cc ampproject/wg-monetization** in all pull request's descriptions. +- It's highly recommended to maintain [an integration test outside AMP repo](../3p/README.md#adding-proper-integration-tests). +- Please consider implementing the `render-start` and `no-content-available` APIs (see [Available APIs](#available-apis)), which helps AMP to provide user a much better ad loading experience. +- [CLA](../docs/contributing.md#contributing-code): for anyone who has trouble to pass the automatic CLA check in a pull request, try to follow the guidelines provided by the CLA Bot. Common mistakes are: 1. Using a different email address in the git commit. 2. Not providing the exact company name in the PR thread. diff --git a/ads/google/a4a/docs/Network-Impl-Guide.md b/ads/google/a4a/docs/Network-Impl-Guide.md index 16f7d351e0d4..1c216df198ad 100644 --- a/ads/google/a4a/docs/Network-Impl-Guide.md +++ b/ads/google/a4a/docs/Network-Impl-Guide.md @@ -4,10 +4,10 @@ This guide outlines the requirements and steps for ad networks to implement Fast Fetch for early ad request and support for AMP ads returned by the ad network to be given preferential rendering. -- _Status: Draft_ -- _Authors: [kjwright@google.com](mailto:kjwright@google.com), - [bradfrizzell@google.com](mailto:bradfrizzell@google.com)_ -- _Last Updated: 1-27-2016_ +- _Status: Draft_ +- _Authors: [kjwright@google.com](mailto:kjwright@google.com), + [bradfrizzell@google.com](mailto:bradfrizzell@google.com)_ +- _Last Updated: 1-27-2016_ -- [Background](#background) -- [Overview](#overview) -- [Detailed design](#detailed-design) - - [Ad server requirements](#ad-server-requirements) - - [SSL](#ssl) - - [AMPHTML ad creative signature](#amphtml-ad-creative-signature) - - [Ad response headers](#ad-response-headers) - - [Creating an AMPHTML ad extension implementation](#creating-an-amphtml-ad-extension-implementation) - - [Create the implementation script](#create-the-implementation-script) - - [Create the configuration file](#create-the-configuration-file) - - [Create documentation](#create-documentation) - - [Create tests](#create-tests) -- [Checklist for ad network implementation](#checklist-for-ad-network-implementation) +- [Background](#background) +- [Overview](#overview) +- [Detailed design](#detailed-design) + - [Ad server requirements](#ad-server-requirements) + - [SSL](#ssl) + - [AMPHTML ad creative signature](#amphtml-ad-creative-signature) + - [Ad response headers](#ad-response-headers) + - [Creating an AMPHTML ad extension implementation](#creating-an-amphtml-ad-extension-implementation) + - [Create the implementation script](#create-the-implementation-script) + - [Create the configuration file](#create-the-configuration-file) + - [Create documentation](#create-documentation) + - [Create tests](#create-tests) +- [Checklist for ad network implementation](#checklist-for-ad-network-implementation) ## Background @@ -208,8 +208,7 @@ _For reference, see [Figure 1: Part A](#figure-1-fast-fetch-rendering-flow)_. }); ``` -Example configs: [AdSense](https://github.com/ampproject/amphtml/blob/main/extensions/amp-ad-network-adsense-impl/0.1/adsense-a4a-config.js#L68). -Usage of Google Ad Manager and AdSense configs can be seen in [\_a4a-config.js](https://github.com/ampproject/amphtml/blob/main/ads/_a4a-config.js). +Example usage of Google Ad Manager and AdSense configs can be seen in [\_a4a-config.js](https://github.com/ampproject/amphtml/blob/main/ads/_a4a-config.js). #### Create documentation @@ -226,14 +225,14 @@ for your AMP ad network implementation. ## Checklist for ad network implementation -- [ ] All Server-AMP communication done with SSL -- [ ] AMP ads sent to validation server -- [ ] Validated AMP ads sent from network to AMP with signature -- [ ] Validated AMP ads sent from network to AMP with appropriate headers -- [ ] File hierarchy created within amphtml/extensions -- [ ] Custom `amp-ad-network--impl.js` overwrites `getAdUrl()` -- [ ] `-a4a-config.js` implements `IsA4AEnabled()` -- [ ] Mapping added for ad network to a4aRegistry map within `_a4a-config.js` -- [ ] Documentation written in `amp-ad-network--impl-internal.md` -- [ ] Tests written in `test-amp-ad-network--impl.js` -- [ ] Pull request merged to the repo +- [ ] All Server-AMP communication done with SSL +- [ ] AMP ads sent to validation server +- [ ] Validated AMP ads sent from network to AMP with signature +- [ ] Validated AMP ads sent from network to AMP with appropriate headers +- [ ] File hierarchy created within amphtml/extensions +- [ ] Custom `amp-ad-network--impl.js` overwrites `getAdUrl()` +- [ ] `-a4a-config.js` implements `IsA4AEnabled()` +- [ ] Mapping added for ad network to a4aRegistry map within `_a4a-config.js` +- [ ] Documentation written in `amp-ad-network--impl-internal.md` +- [ ] Tests written in `test-amp-ad-network--impl.js` +- [ ] Pull request merged to the repo diff --git a/build-system/server/new-server/transforms/utilities/lazy.ts b/build-system/server/new-server/transforms/utilities/lazy.ts index 899088dbaf81..dc1781220755 100644 --- a/build-system/server/new-server/transforms/utilities/lazy.ts +++ b/build-system/server/new-server/transforms/utilities/lazy.ts @@ -1,6 +1,6 @@ export class Lazy { - private declare initializer_: () => T; - private declare value_: T | undefined; + declare private initializer_: () => T; + declare private value_: T | undefined; constructor(initializer: () => T) { this.initializer_ = initializer; diff --git a/build-system/tasks/check-links.js b/build-system/tasks/check-links.js index 917ee205ba10..f8d15402567f 100644 --- a/build-system/tasks/check-links.js +++ b/build-system/tasks/check-links.js @@ -131,6 +131,10 @@ function checkLinksInFile(file) { }, }, ], + // Ignore: + // - 403 [Forbidden], some sites block automated requests. + // - 429 [Too Many Requests], some sites rate-limit requests. + aliveStatusCodes: [200, 403, 429], }; return new Promise((resolve, reject) => { diff --git a/build-system/tasks/e2e/README.md b/build-system/tasks/e2e/README.md index 235cbb568645..2bb555caf71a 100644 --- a/build-system/tasks/e2e/README.md +++ b/build-system/tasks/e2e/README.md @@ -10,22 +10,22 @@ AMP contributors embrace testing to maintain confidence that their code is execu -- [What is an end-to-end test?](#what-is-an-end-to-end-test) -- [Choosing which features to test](#choosing-which-features-to-test) -- [Writing E2E tests](#writing-e2e-tests) -- [Debugging E2E tests](#debugging-e2e-tests) +- [What is an end-to-end test?](#what-is-an-end-to-end-test) +- [Choosing which features to test](#choosing-which-features-to-test) +- [Writing E2E tests](#writing-e2e-tests) +- [Debugging E2E tests](#debugging-e2e-tests) This document is a usage guide. For full test command documentation, consult the following resource: -- [Information on executing tests](../../../docs/testing.md) +- [Information on executing tests](../../../docs/testing.md) ## What is an end-to-end test? Let's compare the test types available to AMP contributors: -- Unit tests -- Integration tests -- End-to-end tests +- Unit tests +- Integration tests +- End-to-end tests Unit tests are useful for testing individual behaviors of a feature or fix. They are cheap to execute since they use mocks heavily to eliminate dependencies that need to also be executed during testing. These should be the most common type of test for a feature. These should fail rarely for reasons other than bugs. @@ -43,13 +43,13 @@ End-to-end tests are able to test a full page as the user's browser would load i End-to-end tests should verify the most important user flows of a component. Prioritize tests for behaviors that would make the page appear very obviously broken if there was a failure. For example: -- The component's initial render -- Primary user interactions - - e.g. clicking the next button on a carousel -- Features with heavy usage by a large number of AMP publishers - - e.g. loading more content at the bottom of an amp page -- Important behaviors that are frequently broken - - e.g. browser updates often break video autoplay behavior +- The component's initial render +- Primary user interactions + - e.g. clicking the next button on a carousel +- Features with heavy usage by a large number of AMP publishers + - e.g. loading more content at the bottom of an amp page +- Important behaviors that are frequently broken + - e.g. browser updates often break video autoplay behavior ## Writing E2E tests diff --git a/build-system/tasks/markdown-toc/test/all-are-complete/allows-paragraph-after-list.md b/build-system/tasks/markdown-toc/test/all-are-complete/allows-paragraph-after-list.md index ec0d908a5b44..1043fcad8fee 100644 --- a/build-system/tasks/markdown-toc/test/all-are-complete/allows-paragraph-after-list.md +++ b/build-system/tasks/markdown-toc/test/all-are-complete/allows-paragraph-after-list.md @@ -7,7 +7,7 @@ amp markdown-toc --fix --> -- [section](#section) +- [section](#section) This paragraph should be preserved. diff --git a/build-system/tasks/markdown-toc/test/all-are-complete/arbitrary-header-indentation.md b/build-system/tasks/markdown-toc/test/all-are-complete/arbitrary-header-indentation.md index ff9b154e3da6..8af05d296ffc 100644 --- a/build-system/tasks/markdown-toc/test/all-are-complete/arbitrary-header-indentation.md +++ b/build-system/tasks/markdown-toc/test/all-are-complete/arbitrary-header-indentation.md @@ -11,7 +11,7 @@ This TOC header has newlines and indentation that doesn't match the lookup strin amp markdown-toc --fix --> -- [section](#section) +- [section](#section) ## section diff --git a/build-system/tasks/markdown-toc/test/all-are-complete/complete.md b/build-system/tasks/markdown-toc/test/all-are-complete/complete.md index c073203aace2..0cec185643a0 100644 --- a/build-system/tasks/markdown-toc/test/all-are-complete/complete.md +++ b/build-system/tasks/markdown-toc/test/all-are-complete/complete.md @@ -7,10 +7,10 @@ amp markdown-toc --fix --> -- [tacos](#tacos) - - [asada](#asada) - - [al pastor](#al-pastor) - - [veggie](#veggie) +- [tacos](#tacos) + - [asada](#asada) + - [al pastor](#al-pastor) + - [veggie](#veggie) ## tacos diff --git a/build-system/tasks/markdown-toc/test/all-are-complete/ignores-unparsable-options.md b/build-system/tasks/markdown-toc/test/all-are-complete/ignores-unparsable-options.md index 121b038c3f58..020b77c2a58f 100644 --- a/build-system/tasks/markdown-toc/test/all-are-complete/ignores-unparsable-options.md +++ b/build-system/tasks/markdown-toc/test/all-are-complete/ignores-unparsable-options.md @@ -11,7 +11,7 @@ This file has unparsable TOC options, but should still have a TOC and should not -- [section](#section) +- [section](#section) ## section diff --git a/build-system/tasks/markdown-toc/test/all-are-complete/uses-options.md b/build-system/tasks/markdown-toc/test/all-are-complete/uses-options.md index af94515431f8..92d7fed72ee1 100644 --- a/build-system/tasks/markdown-toc/test/all-are-complete/uses-options.md +++ b/build-system/tasks/markdown-toc/test/all-are-complete/uses-options.md @@ -9,8 +9,8 @@ -- [included header one](#included-header-one) -- [included header two](#included-header-two) +- [included header one](#included-header-one) +- [included header two](#included-header-two) ## included header one diff --git a/build-system/tasks/markdown-toc/test/some-are-incomplete/complete.md b/build-system/tasks/markdown-toc/test/some-are-incomplete/complete.md index d4f7208478c1..0b426a8657ef 100644 --- a/build-system/tasks/markdown-toc/test/some-are-incomplete/complete.md +++ b/build-system/tasks/markdown-toc/test/some-are-incomplete/complete.md @@ -7,7 +7,7 @@ amp markdown-toc --fix --> -- [What's this?](#whats-this) +- [What's this?](#whats-this) ## What's this? diff --git a/docs/building-an-amp-extension.md b/docs/building-an-amp-extension.md index 3ec2c97c869b..2445768fbb5b 100644 --- a/docs/building-an-amp-extension.md +++ b/docs/building-an-amp-extension.md @@ -16,25 +16,25 @@ rating viewer, you'd do this by building an extension. -- [Getting started](#getting-started) -- [Naming](#naming) -- [Directory structure](#directory-structure) -- [Extend AMP.BaseElement](#extend-ampbaseelement) -- [Element styling](#element-styling) -- [Register element with AMP](#register-element-with-amp) -- [Actions and events](#actions-and-events) -- [Sub-elements ownership](#sub-elements-ownership) -- [Allowing proper validation](#allowing-proper-validation) -- [Performance considerations](#performance-considerations) -- [Layouts supported in your element](#layouts-supported-in-your-element) -- [Experiments](#experiments) -- [Documenting your element](#documenting-your-element) -- [Example of using your extension](#example-of-using-your-extension) -- [Updating build configs](#updating-build-configs) -- [Versioning](#versioning) -- [Unit tests](#unit-tests) -- [Type checking](#type-checking) -- [Example PRs](#example-prs) +- [Getting started](#getting-started) +- [Naming](#naming) +- [Directory structure](#directory-structure) +- [Extend AMP.BaseElement](#extend-ampbaseelement) +- [Element styling](#element-styling) +- [Register element with AMP](#register-element-with-amp) +- [Actions and events](#actions-and-events) +- [Sub-elements ownership](#sub-elements-ownership) +- [Allowing proper validation](#allowing-proper-validation) +- [Performance considerations](#performance-considerations) +- [Layouts supported in your element](#layouts-supported-in-your-element) +- [Experiments](#experiments) +- [Documenting your element](#documenting-your-element) +- [Example of using your extension](#example-of-using-your-extension) +- [Updating build configs](#updating-build-configs) +- [Versioning](#versioning) +- [Unit tests](#unit-tests) +- [Type checking](#type-checking) +- [Example PRs](#example-prs) ## Getting started @@ -137,137 +137,137 @@ AMP.extension('amp-my-element', '0.1', (AMP) => { #### upgradeCallback -- **Default**: Does nothing -- **Override**: Rarely. -- **[Vsync](https://github.com/ampproject/amphtml/blob/main/src/service/vsync-impl.js) Context**: None -- **Usage**: If your extension provides different implementations - depending on a late runtime condition (e.g. type attribute on the - element, platform) -- **Example Usage**: amp-ad, amp-app-banner +- **Default**: Does nothing +- **Override**: Rarely. +- **[Vsync](https://github.com/ampproject/amphtml/blob/main/src/service/vsync-impl.js) Context**: None +- **Usage**: If your extension provides different implementations + depending on a late runtime condition (e.g. type attribute on the + element, platform) +- **Example Usage**: amp-ad, amp-app-banner #### buildCallback -- **Default**: Does nothing -- **Override**: Almost always -- **Vsync Context**: Mutate -- **Usage**: If your element has UI elements this is where you should - create your DOM structure and append it to the element. You can also - read the attributes (e.g. width, height…) the user provided on your - element in this callback. -- **Warning**: Don't load remote resources during the buildCallback. This - not only circumvents the AMP resources manager, but it will also lead to - higher data charges for users because all these resources will be loaded - before layouting needs to happen. -- **Warning 2**: Do the least needed work here, and don't build DOM that - is not needed at this point. +- **Default**: Does nothing +- **Override**: Almost always +- **Vsync Context**: Mutate +- **Usage**: If your element has UI elements this is where you should + create your DOM structure and append it to the element. You can also + read the attributes (e.g. width, height…) the user provided on your + element in this callback. +- **Warning**: Don't load remote resources during the buildCallback. This + not only circumvents the AMP resources manager, but it will also lead to + higher data charges for users because all these resources will be loaded + before layouting needs to happen. +- **Warning 2**: Do the least needed work here, and don't build DOM that + is not needed at this point. #### preconnectCallback -- **Default**: Does nothing. -- **Vsync Context**: None (Neither mutate nor measure) -- **Override**: Sometimes, if your element will be loading remote - resources. -- **Usage**: Use to instruct AMP which hosts to preconnect to, and which - resources to preload/prefetch; this allows AMP to delegate to the browser - to get a performance boost by preconnecting, preloading and prefetching - resources via preconnect service. -- **Example Usage**: [Instagram uses this to - preconnect](https://github.com/ampproject/amphtml/blob/main/extensions/amp-instagram/0.1/amp-instagram.js) - to instagram hosts. +- **Default**: Does nothing. +- **Vsync Context**: None (Neither mutate nor measure) +- **Override**: Sometimes, if your element will be loading remote + resources. +- **Usage**: Use to instruct AMP which hosts to preconnect to, and which + resources to preload/prefetch; this allows AMP to delegate to the browser + to get a performance boost by preconnecting, preloading and prefetching + resources via preconnect service. +- **Example Usage**: [Instagram uses this to + preconnect](https://github.com/ampproject/amphtml/blob/main/extensions/amp-instagram/0.1/amp-instagram.js) + to instagram hosts. #### createPlaceholderCallback -- **Default**: Does nothing. -- **Vsync Context**: Mutate -- **Override**: Sometimes. If your component provides a way to dynamically - create a lightweight placeholder. This gets called only if the element - doesn't already have a publisher-provided placeholder (through [the - placeholder - attribute](https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-html-layout.md#placeholder)). -- **Usage**: Create placeholder DOM and return it. For example, - amp-instagram uses this to create a placeholder dynamically by creating - an amp-img placeholder instead of loading the iframe, leaving the iframe - loading to layoutCallback. -- **Warning**: Only use amp-elements for creating placeholders that - require external resource loading. This allows runtime to create this - early but still defer the resource loading and management to AMP - resources manager. Don't create or load heavyweight resources (e.g. - iframe…). -- **Example Usage**: amp-instagram. +- **Default**: Does nothing. +- **Vsync Context**: Mutate +- **Override**: Sometimes. If your component provides a way to dynamically + create a lightweight placeholder. This gets called only if the element + doesn't already have a publisher-provided placeholder (through [the + placeholder + attribute](https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-html-layout.md#placeholder)). +- **Usage**: Create placeholder DOM and return it. For example, + amp-instagram uses this to create a placeholder dynamically by creating + an amp-img placeholder instead of loading the iframe, leaving the iframe + loading to layoutCallback. +- **Warning**: Only use amp-elements for creating placeholders that + require external resource loading. This allows runtime to create this + early but still defer the resource loading and management to AMP + resources manager. Don't create or load heavyweight resources (e.g. + iframe…). +- **Example Usage**: amp-instagram. #### onLayoutMeasure -- **Default**: Does nothing. -- **Vsync Context**: Measure. -- **Override**: Rarely. -- **Usage**: Use to measure layouts for your element. -- **Example Usage**: amp-iframe +- **Default**: Does nothing. +- **Vsync Context**: Measure. +- **Override**: Rarely. +- **Usage**: Use to measure layouts for your element. +- **Example Usage**: amp-iframe #### layoutCallback -- **Default**: Does nothing. -- **Vsync Context**: Mutate -- **Override**: Almost always. -- **Usage**: Use this to actually render the final version of your - element. If the element should load a video, this is where you load the - video. This needs to return a promise that resolves when the element is - considered "laid out" - usually this means load event has fired but can - be different from element to element. Note that load events usually are - fired very early so if there's another event that your element can - listen to that have a better meaning of ready-ness, use that to resolve - your promise instead - for example: [amp-youtube](https://github.com/ampproject/amphtml/blob/main/extensions/amp-youtube/0.1/amp-youtube.js) uses the - playerready event that the underlying YT Player - iframe sends to resolve the layoutCallback promise. +- **Default**: Does nothing. +- **Vsync Context**: Mutate +- **Override**: Almost always. +- **Usage**: Use this to actually render the final version of your + element. If the element should load a video, this is where you load the + video. This needs to return a promise that resolves when the element is + considered "laid out" - usually this means load event has fired but can + be different from element to element. Note that load events usually are + fired very early so if there's another event that your element can + listen to that have a better meaning of ready-ness, use that to resolve + your promise instead - for example: [amp-youtube](https://github.com/ampproject/amphtml/blob/main/extensions/amp-youtube/0.1/amp-youtube.js) uses the + playerready event that the underlying YT Player + iframe sends to resolve the layoutCallback promise. #### firstLayoutCompleted -- **Default**: Hide element's placeholder. -- **Vsync Context**: Mutate -- **Override**: Sometimes. If you'd like to override default behavior and - not hide the placeholder when the element is considered first laid out. - Sometimes you wanna control when to hide the placeholder. -- **Example Usage**: amp-anim +- **Default**: Hide element's placeholder. +- **Vsync Context**: Mutate +- **Override**: Sometimes. If you'd like to override default behavior and + not hide the placeholder when the element is considered first laid out. + Sometimes you wanna control when to hide the placeholder. +- **Example Usage**: amp-anim #### pauseCallback -- **Default**: Does nothing. -- **Vsync Context**: Mutate -- **Called**: When you swipe away from a document in a viewer. Called on - children of lightbox when you close a lightbox instance, called on - carousel children when the slide is not the active slide. And possibly - other places. -- **Override**: Sometimes. Most likely if you're building a player. -- **Usage**: Use to pause video, slideshow auto-advance...etc -- **Example Usage**: amp-video, amp-youtube +- **Default**: Does nothing. +- **Vsync Context**: Mutate +- **Called**: When you swipe away from a document in a viewer. Called on + children of lightbox when you close a lightbox instance, called on + carousel children when the slide is not the active slide. And possibly + other places. +- **Override**: Sometimes. Most likely if you're building a player. +- **Usage**: Use to pause video, slideshow auto-advance...etc +- **Example Usage**: amp-video, amp-youtube #### resumeCallback -- **Default**: Does nothing. -- **Vsync Context**: Mutate -- **Override**: Sometimes. -- **Usage**: Use to restart the slideshow auto-advance. -- **Note**: This is not used widely yet because it's not possible to - resume video playback for example on mobile. +- **Default**: Does nothing. +- **Vsync Context**: Mutate +- **Override**: Sometimes. +- **Usage**: Use to restart the slideshow auto-advance. +- **Note**: This is not used widely yet because it's not possible to + resume video playback for example on mobile. #### unlayoutOnPause -- **Default**: Returns false. -- **Vsync Context**: Mutate -- **Override**: If your element doesn't provide a pausing mechanism, - instead override this to unlayout the element when AMP tries to pause - it. -- **Return**: True if you want unlayoutCallback to be called when paused. -- **Usage Example**: amp-brightcove +- **Default**: Returns false. +- **Vsync Context**: Mutate +- **Override**: If your element doesn't provide a pausing mechanism, + instead override this to unlayout the element when AMP tries to pause + it. +- **Return**: True if you want unlayoutCallback to be called when paused. +- **Usage Example**: amp-brightcove #### unlayoutCallback -- **Default**: Does nothing. -- **Vsync Context**: Mutate -- **Override**: Sometimes. -- **Usage**: Use to remove and unload heavyweight resources like iframes, - video, audio and others that your element has created. -- **Return**: **True** if your element need to re-layout. -- **Usage Example**: amp-iframe +- **Default**: Does nothing. +- **Vsync Context**: Mutate +- **Override**: Sometimes. +- **Usage**: Use to remove and unload heavyweight resources like iframes, + video, audio and others that your element has created. +- **Return**: **True** if your element need to re-layout. +- **Usage Example**: amp-iframe ## Element styling @@ -725,12 +725,12 @@ File a github issue to cleanup your experiment. Assign it to yourself as a remin Create a .md file that serves as the main documentation for your element. This document should include: -- Summary table -- Overview -- How to use it including code snippets and images -- Examples -- Attributes to specify (optional and required) -- Validation +- Summary table +- Overview +- How to use it including code snippets and images +- Examples +- Attributes to specify (optional and required) +- Validation For samples of element documentation, see: [amp-list](https://github.com/ampproject/amphtml/blob/main/extensions/amp-list/amp-list.md), [amp-instagram](https://github.com/ampproject/amphtml/blob/main/extensions/amp-instagram/amp-instagram.md), [amp-carousel](https://github.com/ampproject/amphtml/blob/main/extensions/amp-carousel/amp-carousel.md) @@ -779,9 +779,9 @@ fine so you can just update the same version. Make sure you write good coverage for your code. We require unit tests for all checked in code. We use the following frameworks for testing: -- [Mocha](https://mochajs.org/), our test framework -- [Karma](https://karma-runner.github.io/), our tests runner -- [Sinon](http://sinonjs.org/), spies, stubs and mocks. +- [Mocha](https://mochajs.org/), our test framework +- [Karma](https://karma-runner.github.io/), our tests runner +- [Sinon](http://sinonjs.org/), spies, stubs and mocks. For faster testing during development, consider using --files argument to only run your extensions' tests. @@ -805,22 +805,22 @@ $ amp check-types ## Example PRs -- Adding new ad-provider - - [Teads](https://github.com/ampproject/amphtml/commit/654ade680d796527345af8ff298a41a7532ee074) - - [EPlanning](https://github.com/ampproject/amphtml/commit/a007543518a07ff77d48297e76bd264cadf36f57) - - [Taboola](https://github.com/ampproject/amphtml/commit/79a58e545939cca0b75e62b2e62147829c59602a) -- Adding embeds that's not iframe-based (requires JS SDK) - - [amp-facebook](https://github.com/ampproject/amphtml/commit/6679db198d8b9d9c38854d93aa04801e8cf6999f) -- Adding iframe based embeds - - [amp-soundcloud](https://github.com/ampproject/amphtml/commit/2ac845641c8eea9e67f17a1d471cfb9bab459fd1) - - [amp-vine](https://github.com/ampproject/amphtml/commit/eb98861b25210f89b41abc9ac52b29d9a4ff45a6) - - [amp-brightcove](https://github.com/ampproject/amphtml/commit/9a0f6089600da0c42e1f3787402a1ced0c377c65) -- Adding non-visual elements - - [amp-font](https://github.com/ampproject/amphtml/commit/ef040b60664a5aad465cb83507d37fae5e361772) - - [amp-install-serviceworker](https://github.com/ampproject/amphtml/commit/e6199cfb5b9d13b0e4bb590b80c09ba3614877e6) -- Adding general UI components - - [amp-sidebar](https://github.com/ampproject/amphtml/commit/99634b18310129f4260e4172cb2750ae7b8ffbf0) - - [amp-image-lightbox](https://github.com/ampproject/amphtml/commit/e6006f9ca516ae5d7d79267976d3df39cc1f9636) - - [amp-accordion](https://github.com/ampproject/amphtml/commit/1aae4eee37ec80c6ea9b822fb43ecce73feb7df6) -- Implementing a video player. - - [amp-jwplayer](https://github.com/ampproject/amphtml/commit/4acdd9f1d70a8a374cb886d3a4778476d13e7daf#diff-f650f38f7840dc8148bacd88733be338) +- Adding new ad-provider + - [Teads](https://github.com/ampproject/amphtml/commit/654ade680d796527345af8ff298a41a7532ee074) + - [EPlanning](https://github.com/ampproject/amphtml/commit/a007543518a07ff77d48297e76bd264cadf36f57) + - [Taboola](https://github.com/ampproject/amphtml/commit/79a58e545939cca0b75e62b2e62147829c59602a) +- Adding embeds that's not iframe-based (requires JS SDK) + - [amp-facebook](https://github.com/ampproject/amphtml/commit/6679db198d8b9d9c38854d93aa04801e8cf6999f) +- Adding iframe based embeds + - [amp-soundcloud](https://github.com/ampproject/amphtml/commit/2ac845641c8eea9e67f17a1d471cfb9bab459fd1) + - [amp-vine](https://github.com/ampproject/amphtml/commit/eb98861b25210f89b41abc9ac52b29d9a4ff45a6) + - [amp-brightcove](https://github.com/ampproject/amphtml/commit/9a0f6089600da0c42e1f3787402a1ced0c377c65) +- Adding non-visual elements + - [amp-font](https://github.com/ampproject/amphtml/commit/ef040b60664a5aad465cb83507d37fae5e361772) + - [amp-install-serviceworker](https://github.com/ampproject/amphtml/commit/e6199cfb5b9d13b0e4bb590b80c09ba3614877e6) +- Adding general UI components + - [amp-sidebar](https://github.com/ampproject/amphtml/commit/99634b18310129f4260e4172cb2750ae7b8ffbf0) + - [amp-image-lightbox](https://github.com/ampproject/amphtml/commit/e6006f9ca516ae5d7d79267976d3df39cc1f9636) + - [amp-accordion](https://github.com/ampproject/amphtml/commit/1aae4eee37ec80c6ea9b822fb43ecce73feb7df6) +- Implementing a video player. + - [amp-jwplayer](https://github.com/ampproject/amphtml/commit/4acdd9f1d70a8a374cb886d3a4778476d13e7daf#diff-f650f38f7840dc8148bacd88733be338) diff --git a/docs/contributing.md b/docs/contributing.md index 33e31952ac36..6a52866ee352 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -15,11 +15,11 @@ How would you like to help? -- [Report a bug](#report-a-bug) -- [Make a suggestion](#make-a-suggestion) -- [Contribute code/features](#contribute-codefeatures) -- [Get started with open source](#get-started-with-open-source) -- [Ongoing participation](#ongoing-participation) +- [Report a bug](#report-a-bug) +- [Make a suggestion](#make-a-suggestion) +- [Contribute code/features](#contribute-codefeatures) +- [Get started with open source](#get-started-with-open-source) +- [Ongoing participation](#ongoing-participation) If you have questions about _using_ AMP or are _encountering problems using AMP_ on your site please visit our [support page](./support.md) for help. @@ -61,13 +61,13 @@ We actively encourage ongoing participation by community members. Technical issues, designs, etc. are discussed using several different channels: -- [GitHub issues](https://github.com/ampproject/amphtml/issues) and [pull requests](https://github.com/ampproject/amphtml/pulls) -- [Slack](https://amphtml.slack.com) ([signup](https://bit.ly/amp-slack-signup)) - - the [#contributing](https://amphtml.slack.com/messages/C9HRJ1GPN/details/) channel is the main channel for you to discuss/ask questions about _contributing_ to the open source project - - if you're _new to contributing_ to AMP stop by [#welcome-contributors](https://amphtml.slack.com/messages/C432AFMFE/details/) to say hi! - - **NOTE: if you have a question about _using AMP on your site_, use [Stack Overflow](https://stackoverflow.com/questions/tagged/amp-html) rather than Slack** as Stack Overflow is more actively monitored for these types of questions - - there are many other Slack channels for more specific topics; after you join our Slack click on the "Channels" header to find other channels you want to participate in -- the [amphtml-discuss Google Group](https://groups.google.com/forum/#!forum/amphtml-discuss) +- [GitHub issues](https://github.com/ampproject/amphtml/issues) and [pull requests](https://github.com/ampproject/amphtml/pulls) +- [Slack](https://amphtml.slack.com) ([signup](https://bit.ly/amp-slack-signup)) + - the [#contributing](https://amphtml.slack.com/messages/C9HRJ1GPN/details/) channel is the main channel for you to discuss/ask questions about _contributing_ to the open source project + - if you're _new to contributing_ to AMP stop by [#welcome-contributors](https://amphtml.slack.com/messages/C432AFMFE/details/) to say hi! + - **NOTE: if you have a question about _using AMP on your site_, use [Stack Overflow](https://stackoverflow.com/questions/tagged/amp-html) rather than Slack** as Stack Overflow is more actively monitored for these types of questions + - there are many other Slack channels for more specific topics; after you join our Slack click on the "Channels" header to find other channels you want to participate in +- the [amphtml-discuss Google Group](https://groups.google.com/forum/#!forum/amphtml-discuss) ### Working groups diff --git a/docs/getting-started-e2e.md b/docs/getting-started-e2e.md index 8acd0d12ca1a..2c4954230ebb 100644 --- a/docs/getting-started-e2e.md +++ b/docs/getting-started-e2e.md @@ -15,44 +15,44 @@ If you do not yet have a specific code contribution project in mind as you go th amp markdown-toc --fix --> -- [How to get help](#how-to-get-help) -- [Intro to Git and GitHub](#intro-to-git-and-github) -- [Set up your GitHub account and Git](#set-up-your-github-account-and-git) -- [Get a copy of the amphtml code](#get-a-copy-of-the-amphtml-code) -- [Understanding repositories](#understanding-repositories) -- [Creating your GitHub fork and your local repository](#creating-your-github-fork-and-your-local-repository) -- [Set up aliases for the remote Git repositories](#set-up-aliases-for-the-remote-git-repositories) -- [Building AMP and starting a local server](#building-amp-and-starting-a-local-server) -- [Create a Git branch](#create-a-git-branch) -- [Pull the latest changes from the amphtml repository](#pull-the-latest-changes-from-the-amphtml-repository) -- [Edit files and commit them](#edit-files-and-commit-them) -- [Code quality and style](#code-quality-and-style) - - [Workflow for Visual Studio Code](#workflow-for-visual-studio-code) - - [To automatically fix JS files on save](#to-automatically-fix-js-files-on-save) - - [To automatically fix non-JS files on save](#to-automatically-fix-non-js-files-on-save) - - [Manually fixing code](#manually-fixing-code) -- [Testing your changes](#testing-your-changes) -- [Running tests locally](#running-tests-locally) -- [Running all the CircleCI checks locally](#running-all-the-circleci-checks-locally) -- [Adding tests](#adding-tests) -- [Perform manual tests](#perform-manual-tests) -- [Push your changes to your GitHub fork](#push-your-changes-to-your-github-fork) -- [Send a Pull Request (i.e. request a code review)](#send-a-pull-request-ie-request-a-code-review) -- [Respond to Pull Request comments](#respond-to-pull-request-comments) -- [Delete your branch](#delete-your-branch) -- [See your changes in production](#see-your-changes-in-production) -- [⚡⚡⚡... (Next steps)](#%E2%9A%A1%E2%9A%A1%E2%9A%A1-next-steps) -- [Other resources](#other-resources) +- [How to get help](#how-to-get-help) +- [Intro to Git and GitHub](#intro-to-git-and-github) +- [Set up your GitHub account and Git](#set-up-your-github-account-and-git) +- [Get a copy of the amphtml code](#get-a-copy-of-the-amphtml-code) +- [Understanding repositories](#understanding-repositories) +- [Creating your GitHub fork and your local repository](#creating-your-github-fork-and-your-local-repository) +- [Set up aliases for the remote Git repositories](#set-up-aliases-for-the-remote-git-repositories) +- [Building AMP and starting a local server](#building-amp-and-starting-a-local-server) +- [Create a Git branch](#create-a-git-branch) +- [Pull the latest changes from the amphtml repository](#pull-the-latest-changes-from-the-amphtml-repository) +- [Edit files and commit them](#edit-files-and-commit-them) +- [Code quality and style](#code-quality-and-style) + - [Workflow for Visual Studio Code](#workflow-for-visual-studio-code) + - [To automatically fix JS files on save](#to-automatically-fix-js-files-on-save) + - [To automatically fix non-JS files on save](#to-automatically-fix-non-js-files-on-save) + - [Manually fixing code](#manually-fixing-code) +- [Testing your changes](#testing-your-changes) +- [Running tests locally](#running-tests-locally) +- [Running all the CircleCI checks locally](#running-all-the-circleci-checks-locally) +- [Adding tests](#adding-tests) +- [Perform manual tests](#perform-manual-tests) +- [Push your changes to your GitHub fork](#push-your-changes-to-your-github-fork) +- [Send a Pull Request (i.e. request a code review)](#send-a-pull-request-ie-request-a-code-review) +- [Respond to Pull Request comments](#respond-to-pull-request-comments) +- [Delete your branch](#delete-your-branch) +- [See your changes in production](#see-your-changes-in-production) +- [⚡⚡⚡... (Next steps)](#%E2%9A%A1%E2%9A%A1%E2%9A%A1-next-steps) +- [Other resources](#other-resources) # How to get help If you have a question or are unsure about something while following this end-to-end guide, you can get help from the AMP open source community in many ways: -- If you are tackling a [Good First Issue](https://github.com/ampproject/amphtml/labels/good%20first%20issue) or other GitHub issue you can ask a question as a comment on the issue directly. This works particularly well if the question is about how to make progress on that specific issue. +- If you are tackling a [Good First Issue](https://github.com/ampproject/amphtml/labels/good%20first%20issue) or other GitHub issue you can ask a question as a comment on the issue directly. This works particularly well if the question is about how to make progress on that specific issue. -- The [#welcome-contributors](https://amphtml.slack.com/messages/welcome-contributors/) channel on Slack is a place for new contributors getting up to speed in AMP to find help. You should feel comfortable asking any question in there no matter how basic it may seem to you (e.g. problems getting Git set up, errors during a build, etc.). We'll send you an [invitation](https://docs.google.com/forms/d/e/1FAIpQLSd83J2IZA6cdR6jPwABGsJE8YL4pkypAbKMGgUZZriU7Qu6Tg/viewform?fbzx=4406980310789882877) if you're not already on the AMP Slack. +- The [#welcome-contributors](https://amphtml.slack.com/messages/welcome-contributors/) channel on Slack is a place for new contributors getting up to speed in AMP to find help. You should feel comfortable asking any question in there no matter how basic it may seem to you (e.g. problems getting Git set up, errors during a build, etc.). We'll send you an [invitation](https://docs.google.com/forms/d/e/1FAIpQLSd83J2IZA6cdR6jPwABGsJE8YL4pkypAbKMGgUZZriU7Qu6Tg/viewform?fbzx=4406980310789882877) if you're not already on the AMP Slack. -- You can also ask questions on [amphtml-discuss@googlegroups.com](https://groups.google.com/forum/#!forum/amphtml-discuss). +- You can also ask questions on [amphtml-discuss@googlegroups.com](https://groups.google.com/forum/#!forum/amphtml-discuss). # Intro to Git and GitHub @@ -60,9 +60,9 @@ People who have never used Git or GitHub before can find them intimidating--even Despite the similarity in names, Git & GitHub are different: -- Git is a version control system. You'll install the Git client locally and run Git commands to grab code from a Git repository, make changes and submit code. You don't need to use GitHub to use Git, but the AMP's Git repository happens to be hosted on GitHub. +- Git is a version control system. You'll install the Git client locally and run Git commands to grab code from a Git repository, make changes and submit code. You don't need to use GitHub to use Git, but the AMP's Git repository happens to be hosted on GitHub. -- GitHub hosts Git repositories and provides other tools that make managing projects easier (like a GUI for code reviews, bug tracking, etc.). +- GitHub hosts Git repositories and provides other tools that make managing projects easier (like a GUI for code reviews, bug tracking, etc.). To contribute to AMP you'll use Git to grab a copy of the code from the [amphtml Git repository on GitHub](https://github.com/ampproject/amphtml), make changes locally and push your changes back up to your own Git repository on GitHub so you can get your code changes reviewed and merged into the amphtml codebase. @@ -80,19 +80,19 @@ One of the central concepts of Git is the _repository_, where files are stored a The process of getting the amphtml code, making changes, getting your changes reviewed and then having your changes become a part of AMP involves _three_ repositories: -- The first repository is the **amphtml repository** mentioned above. When you want to fix a bug or add a feature to AMP your goal is to get your code to become part of this repository (_merged_ in Git terms). The amphtml repository is an example of a _remote_ repository because it's stored in a server that your Git client connects to. +- The first repository is the **amphtml repository** mentioned above. When you want to fix a bug or add a feature to AMP your goal is to get your code to become part of this repository (_merged_ in Git terms). The amphtml repository is an example of a _remote_ repository because it's stored in a server that your Git client connects to. -- You'll create a **_fork_ of the amphtml repository** on GitHub before you make your first change. This creates your own complete copy of all of the files from the amphtml repository which gives you a place to put your changes without affecting other people's work. Since your fork is on GitHub's servers this is also a _remote_ repository. Once you create your fork you'll be able to browse a copy of all of the files on the Web UI at `https://github.com//amphtml`. +- You'll create a **_fork_ of the amphtml repository** on GitHub before you make your first change. This creates your own complete copy of all of the files from the amphtml repository which gives you a place to put your changes without affecting other people's work. Since your fork is on GitHub's servers this is also a _remote_ repository. Once you create your fork you'll be able to browse a copy of all of the files on the Web UI at `https://github.com//amphtml`. -- In general you won't be making changes directly on your fork on GitHub since GitHub provides very limited edit and build capabilities. Instead you'll create a copy of your fork in a **_local_ repository** which will download all of the amphtml files to your computer. This is where you'll typically be building AMP, making changes, testing them out, etc. +- In general you won't be making changes directly on your fork on GitHub since GitHub provides very limited edit and build capabilities. Instead you'll create a copy of your fork in a **_local_ repository** which will download all of the amphtml files to your computer. This is where you'll typically be building AMP, making changes, testing them out, etc. If you are new to Git it may seem surprising that there are three different repositories involved but each one serves its purpose. Here's how they interact in a typical scenario: -- You'll make changes on your computer (your local repository). +- You'll make changes on your computer (your local repository). -- When you're done you'll push these changes to your fork on GitHub so that others can see your changes and review them before they become part of the amphtml repository. +- When you're done you'll push these changes to your fork on GitHub so that others can see your changes and review them before they become part of the amphtml repository. -- When the changes have been approved by someone with permission to do so, that person will handle merging your changes from your GitHub fork to the amphtml repository. +- When the changes have been approved by someone with permission to do so, that person will handle merging your changes from your GitHub fork to the amphtml repository. Note that each of these repositories has a complete copy of the entire amphtml codebase. If your local repository is on your computer and you lose your internet connection you'll still be able to make changes to any file in your local repository. Part of the workflow for Git that we'll go through is how you keep these three repositories in sync. @@ -102,13 +102,12 @@ One thing that might put your mind at ease: if you aren't in a [role](https://gi To create your fork on GitHub and your local copy of that fork: -- Create a fork of the amphtml repository on GitHub by going to [https://github.com/ampproject/amphtml](https://github.com/ampproject/amphtml) and clicking the "Fork" button near the top. Your GitHub fork will now be visible at `https://github.com//amphtml`. During local development, this will be referred to by `git` as `origin`. +- Create a fork of the amphtml repository on GitHub by going to [https://github.com/ampproject/amphtml](https://github.com/ampproject/amphtml) and clicking the "Fork" button near the top. Your GitHub fork will now be visible at `https://github.com//amphtml`. During local development, this will be referred to by `git` as `origin`. -- Create your local copy (or _clone_) of your fork: +- Create your local copy (or _clone_) of your fork: + - go to a local directory on your computer where you want to put a copy of the code, e.g. `~/src/ampproject` - - go to a local directory on your computer where you want to put a copy of the code, e.g. `~/src/ampproject` - - - run the `git clone` command using the address for your remote repository (your GitHub fork): + - run the `git clone` command using the address for your remote repository (your GitHub fork): ```sh git clone git@github.com:/amphtml.git @@ -157,7 +156,7 @@ git branch -u upstream/main main Now that you have all of the files copied locally you can actually build the code and run a local server to try things out. We use Node.js along with several npm packages to build amphtml and start up a local server that lets you try out your changes. -- Install the latest LTS version of [Node.js](https://nodejs.org/) (which includes `npm`). An easy way to do so is by first installing `nvm`. Follow the macOS / Linux instructions [here](https://github.com/creationix/nvm), or the Windows instructions [here](https://github.com/coreybutler/nvm-windows). Then run the install command(s): +- Install the latest LTS version of [Node.js](https://nodejs.org/) (which includes `npm`). An easy way to do so is by first installing `nvm`. Follow the macOS / Linux instructions [here](https://github.com/creationix/nvm), or the Windows instructions [here](https://github.com/coreybutler/nvm-windows). Then run the install command(s): ```sh # macOS / Linux @@ -169,7 +168,7 @@ Now that you have all of the files copied locally you can actually build the cod nvm use ``` -- In your local repository directory (e.g. `~/src/ampproject/amphtml`), install the packages that AMP uses by running this command: +- In your local repository directory (e.g. `~/src/ampproject/amphtml`), install the packages that AMP uses by running this command: ``` npm install ``` @@ -187,19 +186,19 @@ You can browse the [http://localhost:8000/examples](http://localhost:8000/exampl Note that by default each of the pages in the /examples directory uses the unminified AMP JavaScript from your local server. You can also change which JS to load from local server by hitting the `/serve_mode=` endpoint: -- [http://localhost:8000/serve_mode=default](http://localhost:8000/serve_mode=default) +- [http://localhost:8000/serve_mode=default](http://localhost:8000/serve_mode=default) This is the default. Unminified AMP JavaScript is served from the local server. For local development you will usually want to serve unminified JS to test your changes. -- [http://localhost:8000/serve_mode=compiled](http://localhost:8000/serve_mode=compiled) +- [http://localhost:8000/serve_mode=compiled](http://localhost:8000/serve_mode=compiled) Minified AMP JavaScript is served from the local server. This is only available after running `amp dist --fortesting`. -- [http://localhost:8000/serve_mode=cdn](http://localhost:8000/serve_mode=cdn) +- [http://localhost:8000/serve_mode=cdn](http://localhost:8000/serve_mode=cdn) Minified AMP JavaScript is served from `cdn.ampproject.org`. -- http://localhost:8000/serve_mode= +- http://localhost:8000/serve_mode= E.g. http://localhost:8000/serve_mode=001907161745080 @@ -275,18 +274,17 @@ If there are changes that conflict with changes on your branch (e.g. someone mod The common workflow for making changes to files in Git is: -- Edit some files using your favorite editor - -- If your code requires a new dependency, run `npm install [--save-dev] `, which will automatically update `package.json` and `package-lock.json` +- Edit some files using your favorite editor - - If it is a build-time dependency, use the `--save-dev` flag - - If it is a runtime dependency, add it to `build-system/compile/sources.js` +- If your code requires a new dependency, run `npm install [--save-dev] `, which will automatically update `package.json` and `package-lock.json` + - If it is a build-time dependency, use the `--save-dev` flag + - If it is a runtime dependency, add it to `build-system/compile/sources.js` -- If you manually edited `package.json`, run `npm install` to install the dependency and generate an updated `package-lock.json` file +- If you manually edited `package.json`, run `npm install` to install the dependency and generate an updated `package-lock.json` file -- Tell Git that you care about these changes by _staging_ them using the `git add` command +- Tell Git that you care about these changes by _staging_ them using the `git add` command -- Create a checkpoint (called a _commit_) that bundles together the changes you've staged by using the `git commit` command +- Create a checkpoint (called a _commit_) that bundles together the changes you've staged by using the `git commit` command Git commits bundle together related changes into a logical unit. (If you're familiar with some other source control systems this terminology may make you think that when you create a commit you're "checking in" your code to the amphtml repository; that's _not_ what a Git commit is.) @@ -334,18 +332,18 @@ Note that you _can_ add changes into an existing commit but that opens up some a AMP uses the following tools for code quality and style: -- [Eslint](https://eslint.org/) is used to ensure the code quality of JS files. - - Default rules can be found in [.eslintrc.js](../.eslintrc.js) files across the repo. - - Custom rules can be found in [build-system/eslint-rules/](../build-system/eslint-rules/index.js). -- [Prettier](https://prettier.io/) is used to standardize the code style and formatting of JS files and several non-JS files. - - Default and file-specific rules can be found in [.prettierrc](../.prettierrc). +- [Eslint](https://eslint.org/) is used to ensure the code quality of JS files. + - Default rules can be found in [.eslintrc.js](../.eslintrc.js) files across the repo. + - Custom rules can be found in [build-system/eslint-rules/](../build-system/eslint-rules/index.js). +- [Prettier](https://prettier.io/) is used to standardize the code style and formatting of JS files and several non-JS files. + - Default and file-specific rules can be found in [.prettierrc](../.prettierrc). To easily ensure code quality and style during development, here are some recommendations: -- Use a code editor with Eslint and Prettier support. -- [Here](https://eslint.org/docs/user-guide/integrations#editors) is a list of editors with Eslint extension support. -- [Here](https://prettier.io/docs/en/editors.html) is a list of editors with Prettier extension support. -- Set your editor to automatically format your code on save. +- Use a code editor with Eslint and Prettier support. +- [Here](https://eslint.org/docs/user-guide/integrations#editors) is a list of editors with Eslint extension support. +- [Here](https://prettier.io/docs/en/editors.html) is a list of editors with Prettier extension support. +- Set your editor to automatically format your code on save. ### Workflow for Visual Studio Code @@ -353,14 +351,14 @@ Several AMP developers use [Visual Studio Code](https://code.visualstudio.com/). #### To automatically fix JS files on save -- Install the [Eslint plugin](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). -- The `eslint.autoFixOnSave` setting is already enabled for the project in [.vscode/settings.json](../.vscode/settings.json), and will cause all JS files to automatically get formatted on save. +- Install the [Eslint plugin](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). +- The `eslint.autoFixOnSave` setting is already enabled for the project in [.vscode/settings.json](../.vscode/settings.json), and will cause all JS files to automatically get formatted on save. #### To automatically fix non-JS files on save -- Install the [Prettier plugin](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). -- Install the [JSON5 syntax plugin](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-json5). (Used by `OWNERS` files. VS Code does not natively support it.) -- Language and file level settings are already enabled for the project in [.vscode/settings.json](../.vscode/settings.json), and will cause several non-JS files to automatically get formatted on save. +- Install the [Prettier plugin](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). +- Install the [JSON5 syntax plugin](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-json5). (Used by `OWNERS` files. VS Code does not natively support it.) +- Language and file level settings are already enabled for the project in [.vscode/settings.json](../.vscode/settings.json), and will cause several non-JS files to automatically get formatted on save. ### Manually fixing code @@ -406,10 +404,10 @@ amp pr-check Notes: -- This will force a clean build and run all the PR checks one by one. -- Just like on CircleCI, a failing check will prevent subsequent checks from being run. -- The `amp visual-diff` check will be skipped unless you have set up a Percy account as described in the [Testing](testing.md#running-visual-diff-tests-locally) guide. -- Unit and integration tests will be run on local Chrome. +- This will force a clean build and run all the PR checks one by one. +- Just like on CircleCI, a failing check will prevent subsequent checks from being run. +- The `amp visual-diff` check will be skipped unless you have set up a Percy account as described in the [Testing](testing.md#running-visual-diff-tests-locally) guide. +- Unit and integration tests will be run on local Chrome. ## Adding tests @@ -431,8 +429,8 @@ amp unit --files=extensions/amp-story/1.0/test/test-amp-story-embedded-component Testing tips: -- Use Mocha's [`.only()`](https://mochajs.org/#exclusive-tests) feature to exclusively run certain test-cases or suites. -- Add `--watch` to your `amp unit` command to automatically re-run tests on code changes. +- Use Mocha's [`.only()`](https://mochajs.org/#exclusive-tests) feature to exclusively run certain test-cases or suites. +- Add `--watch` to your `amp unit` command to automatically re-run tests on code changes. For more help, see [How to get help](#how-to-get-help). @@ -512,13 +510,13 @@ This is a good time to make sure that you've signed in to the services used to v On the Pull Request page you can see that a few checks are running: -- The tests are being run on [CircleCI](https://app.circleci.com/pipelines/github/ampproject/amphtml) +- The tests are being run on [CircleCI](https://app.circleci.com/pipelines/github/ampproject/amphtml) -- The system is verifying that you have signed a CLA (Contributor License Agreement). If this is your first time submitting a Pull Request for AMP on GitHub you'll need to sign a CLA. (Make sure the email address you use to sign the CLA is the same one that you configured Git with.) See details in the [Contributing code](../docs/contributing.md#contributing-code) documentation. +- The system is verifying that you have signed a CLA (Contributor License Agreement). If this is your first time submitting a Pull Request for AMP on GitHub you'll need to sign a CLA. (Make sure the email address you use to sign the CLA is the same one that you configured Git with.) See details in the [Contributing code](../docs/contributing.md#contributing-code) documentation. -- Your code is going through static analysis by [LGTM](https://lgtm.com/projects/g/ampproject/amphtml/). +- Your code is going through static analysis by [LGTM](https://lgtm.com/projects/g/ampproject/amphtml/). -- Visual diff tests that are run on CircleCI are being analyzed by [Percy](http://percy.io/ampproject/amphtml). +- Visual diff tests that are run on CircleCI are being analyzed by [Percy](http://percy.io/ampproject/amphtml). If you don't hear back from your reviewer within 2 business days, feel free to ping the pull request by adding a comment. @@ -581,10 +579,10 @@ If you're looking for ideas on your next contribution feel free to reach out to This end-to-end guide provided enough details to get a basic understanding of a typical workflow for contributing code to the AMP open source project. If you find yourself wanting to know more there are a lot of resources available. Here are a few: -- The ["Building an AMP Extension" guide](https://github.com/ampproject/amphtml/blob/main/docs/building-an-amp-extension.md) provides step-by-step instructions for a common type of code contribution to AMP. Even if your project involves modifying an existing AMP component, this guide will give you an overview of how AMP components work. -- GitHub has a lot of helpful introductory material, including: - - a [Hello World tutorial](https://guides.github.com/activities/hello-world/) that's a bit less in depth than this guide, but it covers things like creating a new repository and merging in code after a pull request - - the [Git cheat sheet](https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf) from GitHub provides a quick reference to some common commands, including many we didn't cover in this guide (such as [diff](https://www.git-tower.com/learn/git/ebook/en/command-line/advanced-topics/diffs) and [log](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)) - - a [Training & Guides video series](https://www.youtube.com/user/GitHubGuides) -- The official [Git docs](https://git-scm.com/doc) have a lot of information including the [reference docs](https://git-scm.com/docs) and an online version of [Pro Git](https://git-scm.com/book/en/v2). -- You may see discussions about the difference between rebasing and merging in Git, and we glossed over the details in this guide. If you're curious about the difference the Atlassian [Merging vs. Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) tutorial has a good explanation. +- The ["Building an AMP Extension" guide](https://github.com/ampproject/amphtml/blob/main/docs/building-an-amp-extension.md) provides step-by-step instructions for a common type of code contribution to AMP. Even if your project involves modifying an existing AMP component, this guide will give you an overview of how AMP components work. +- GitHub has a lot of helpful introductory material, including: + - a [Hello World tutorial](https://guides.github.com/activities/hello-world/) that's a bit less in depth than this guide, but it covers things like creating a new repository and merging in code after a pull request + - the [Git cheat sheet](https://education.github.com/git-cheat-sheet-education.pdf) from GitHub provides a quick reference to some common commands, including many we didn't cover in this guide (such as [diff](https://www.git-tower.com/learn/git/ebook/en/command-line/advanced-topics/diffs) and [log](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)) + - a [Training & Guides video series](https://www.youtube.com/playlist?list=PL0lo9MOBetEFcp4SCWinBdpml9B2U25-f) +- The official [Git docs](https://git-scm.com/doc) have a lot of information including the [reference docs](https://git-scm.com/docs) and an online version of [Pro Git](https://git-scm.com/book/en/v2). +- You may see discussions about the difference between rebasing and merging in Git, and we glossed over the details in this guide. If you're curious about the difference the Atlassian [Merging vs. Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) tutorial has a good explanation. diff --git a/docs/release-schedule.md b/docs/release-schedule.md index d40655864637..4442e5608f18 100644 --- a/docs/release-schedule.md +++ b/docs/release-schedule.md @@ -7,15 +7,15 @@ amp markdown-toc --fix --> -- [Release Channels](#release-channels) - - [Nightly](#nightly) - - [Weekly](#weekly) - - [Beta and Experimental channels](#beta-and-experimental-channels) - - [Long-Term Stable (lts)](#long-term-stable-lts) -- [Determining if your change is in a release](#determining-if-your-change-is-in-a-release) -- [Release Cadence](#release-cadence) - - [Detailed schedule](#detailed-schedule) - - [Release Freezes](#release-freezes) +- [Release Channels](#release-channels) + - [Nightly](#nightly) + - [Weekly](#weekly) + - [Beta and Experimental channels](#beta-and-experimental-channels) + - [Long-Term Stable (lts)](#long-term-stable-lts) +- [Determining if your change is in a release](#determining-if-your-change-is-in-a-release) +- [Release Cadence](#release-cadence) + - [Detailed schedule](#detailed-schedule) + - [Release Freezes](#release-freezes) A new release of AMP is pushed to all AMP pages every week on Tuesday. **Once a change in AMP is merged into the main branch of the amphtml repository, it will typically take 1-2 weeks for the change to be live for all users.** @@ -51,13 +51,13 @@ It is possible to opt into these channels. See the [opt-in section](developing.m Opting into the _Beta Channel_ is intended for: -- testing and playing with the version of the AMP runtime that will be released soon -- using in Quality Assurance (QA) to ensure that your site is compatible with the next version of AMP +- testing and playing with the version of the AMP runtime that will be released soon +- using in Quality Assurance (QA) to ensure that your site is compatible with the next version of AMP The _Experimental Channel_ is intended for: -- testing and playing with new features not yet available to all users -- using in Quality Assurance (QA) to ensure that your site is compatible with upcoming features of AMP that are still under development +- testing and playing with new features not yet available to all users +- using in Quality Assurance (QA) to ensure that your site is compatible with upcoming features of AMP that are still under development The _Experimental Channel_ **may be less stable** and it may contain features not yet available to all users. @@ -75,8 +75,8 @@ Important: Publishers using the **lts** release channel should not use newly int You can determine what changes are in a given release using one of the following: -- The [_Type: Release_ GitHub issues](https://github.com/ampproject/amphtml/labels/Type%3A%20Release) for each release will include a link to the specific [release page](https://github.com/ampproject/amphtml/releases) listing the changes contained in that release. -- The [_PR Use: In Beta / Experimental_](https://github.com/ampproject/amphtml/issues?q=label%3A%22PR+use%3A+In+Beta+%2F+Experimental%22), [_PR Use: In Stable_](https://github.com/ampproject/amphtml/issues?utf8=%E2%9C%93&q=label%3A%22PR%20use%3A%20In%20Production%22), and [_PR Use: In LTS_](https://github.com/ampproject/amphtml/issues?utf8=%E2%9C%93&q=label%3A%22PR%20use%3A%20In%20LTS%22) labels are added to PRs when they've made it into a _weekly_ or **lts** release. There may be a delay between when the release is created and when the label is added. +- The [_Type: Release_ GitHub issues](https://github.com/ampproject/amphtml/labels/Type%3A%20Release) for each release will include a link to the specific [release page](https://github.com/ampproject/amphtml/releases) listing the changes contained in that release. +- The [_PR Use: In Beta / Experimental_](https://github.com/ampproject/amphtml/issues?q=label%3A%22PR+use%3A+In+Beta+%2F+Experimental%22), [_PR Use: In Stable_](https://github.com/ampproject/amphtml/issues?utf8=%E2%9C%93&q=label%3A%22PR%20use%3A%20In%20Production%22), and [_PR Use: In LTS_](https://github.com/ampproject/amphtml/issues?utf8=%E2%9C%93&q=label%3A%22PR%20use%3A%20In%20LTS%22) labels are added to PRs when they've made it into a _weekly_ or **lts** release. There may be a delay between when the release is created and when the label is added. ## Release Cadence @@ -84,9 +84,9 @@ We are intentionally cautious with our release cadence. In determining how often we should push new versions of AMP to everyone, we have to weigh many factors including: -- stability for the millions of sites/billions of pages built using AMP -- cache-busting that might happen when we push a new version -- the desire to get new features out quickly +- stability for the millions of sites/billions of pages built using AMP +- cache-busting that might happen when we push a new version +- the desire to get new features out quickly After considering all of these factors, we have arrived at the 1-2 week push cycle. Thus far, we have found this to be a reasonable compromise, but we will continue to evaluate all of these factors and may make changes in the future. @@ -94,11 +94,11 @@ After considering all of these factors, we have arrived at the 1-2 week push cyc We try to stick to this schedule as closely as possible, though complications may cause delays. You can track the latest status about any release in the [_Type: Release_ GitHub issues](https://github.com/ampproject/amphtml/labels/Type%3A%20Release) and the [AMP Slack #release channel](https://amphtml.slack.com/messages/C4NVAR0H3/) ([sign up for Slack](https://bit.ly/amp-slack-signup)). -- Every weeknight: a new **nightly** build is automatically cut and released to the [AMP Nightly Channel](#nightly). -- Tuesday @ [11am Pacific](https://www.google.com/search?q=11am+pacific+in+current+time+zone): new **experimental** and **beta** releases are created from a recent known-good nightly channel release and are served to users who opted into the [AMP Experimental Channel](#amp-experimental-and-beta-channels) or [AMP Beta Channel](#amp-experimental-and-beta-channels), respectively. -- Wednesday: we check bug reports for _Experimental Channel_ and _Beta Channel_ users and if everything looks fine, we push the **beta** to 1% of AMP pages -- Thursday-Monday: we continue to monitor error rates and bug reports for _Experimental Channel_ and _Beta Channel_ users and the 1% of pages with the **experimental**/**beta** builds -- Tuesday the following week: the **beta** release is fully promoted to **stable** (i.e. all AMP pages will now use this release) +- Every weeknight: a new **nightly** build is automatically cut and released to the [AMP Nightly Channel](#nightly). +- Tuesday @ [11am Pacific](https://www.google.com/search?q=11am+pacific+in+current+time+zone): new **experimental** and **beta** releases are created from a recent known-good nightly channel release and are served to users who opted into the [AMP Experimental Channel](#amp-experimental-and-beta-channels) or [AMP Beta Channel](#amp-experimental-and-beta-channels), respectively. +- Wednesday: we check bug reports for _Experimental Channel_ and _Beta Channel_ users and if everything looks fine, we push the **beta** to 1% of AMP pages +- Thursday-Monday: we continue to monitor error rates and bug reports for _Experimental Channel_ and _Beta Channel_ users and the 1% of pages with the **experimental**/**beta** builds +- Tuesday the following week: the **beta** release is fully promoted to **stable** (i.e. all AMP pages will now use this release) ### Release Freezes @@ -106,17 +106,17 @@ There are occasions when we will skip a release of AMP to production, known as a If a one week release freeze is announced for Week N: -- The previous week's **stable** release will remain for an extra week, i.e. a new release will not be promoted to **stable** in Week N as would normally be the case. -- However, new **beta** and **experimental** releases will be created during the freeze week (Week N). -- The normal schedule will resume in Week N+1, i.e. the **experimental**/**beta** releases from Week N are promoted to **stable** in Week N+1. In addition, new **experimental**/**beta** releases are created in Week N+1 and will be promoted to **stable** during Week N+2. -- If the **stable** release promoted during Week N-1 was originally scheduled to be promoted to **lts** during Week N, it will now be promoted to **lts** on the Monday of Week N+1. -- **nightly** releases are still generated and promoted, as they are fully automated. +- The previous week's **stable** release will remain for an extra week, i.e. a new release will not be promoted to **stable** in Week N as would normally be the case. +- However, new **beta** and **experimental** releases will be created during the freeze week (Week N). +- The normal schedule will resume in Week N+1, i.e. the **experimental**/**beta** releases from Week N are promoted to **stable** in Week N+1. In addition, new **experimental**/**beta** releases are created in Week N+1 and will be promoted to **stable** during Week N+2. +- If the **stable** release promoted during Week N-1 was originally scheduled to be promoted to **lts** during Week N, it will now be promoted to **lts** on the Monday of Week N+1. +- **nightly** releases are still generated and promoted, as they are fully automated. A release freeze may happen due to: -- Times when there are not enough people available to push the AMP release to **stable** and monitor it. Currently, most of the people performing AMP releases are based in the United States, so this will usually be the weeks of the major US holidays of Independence Day (July 4), Thanksgiving (fourth Thursday in November), Christmas (25 December), and New Year's Eve/Day (December 31/January 1). -- An emergency situation, such as a security or privacy issue as determined by the [Technical Steering Committee (TSC)](https://github.com/ampproject/meta-tsc) or the people performing the release. -- Other situations when the stability of the codebase is deemed to be particularly important as determined by the TSC. +- Times when there are not enough people available to push the AMP release to **stable** and monitor it. Currently, most of the people performing AMP releases are based in the United States, so this will usually be the weeks of the major US holidays of Independence Day (July 4), Thanksgiving (fourth Thursday in November), Christmas (25 December), and New Year's Eve/Day (December 31/January 1). +- An emergency situation, such as a security or privacy issue as determined by the [Technical Steering Committee (TSC)](https://github.com/ampproject/meta-tsc) or the people performing the release. +- Other situations when the stability of the codebase is deemed to be particularly important as determined by the TSC. In all cases, except emergencies, the release freezes will be announced at least one month in advance. diff --git a/docs/spec/amp-managing-user-state.md b/docs/spec/amp-managing-user-state.md index bf8b5189e087..7ad8214aa23d 100644 --- a/docs/spec/amp-managing-user-state.md +++ b/docs/spec/amp-managing-user-state.md @@ -11,26 +11,26 @@ -- [Background](#background) - - [Display contexts for AMP pages](#display-contexts-for-amp-pages) - - [Multiple contexts means multiple state management](#multiple-contexts-means-multiple-state-management) -- [Implementation guide](#implementation-guide) - - [Before getting started](#before-getting-started) - - [Task 1: For non-AMP pages on the publisher origin, set up an identifier and send analytics pings](#task-1-for-non-amp-pages-on-the-publisher-origin-set-up-an-identifier-and-send-analytics-pings) - - [Task 2: For AMP pages, set up an identifier and send analytics pings by including Client ID replacement in amp-analytics pings](#task-2-for-amp-pages-set-up-an-identifier-and-send-analytics-pings-by-including-client-id-replacement-in-amp-analytics-pings) - - [Task 3: Process analytics pings from pages on the publisher origin](#task-3-process-analytics-pings-from-pages-on-the-publisher-origin) - - [Task 4: Process analytics pings from AMP cache or AMP viewer display contexts and establish identifier mappings (if needed)](#task-4-process-analytics-pings-from-amp-cache-or-amp-viewer-display-contexts-and-establish-identifier-mappings-if-needed) - - [Task 5: Using Client ID in linking and form submission](#task-5-using-client-id-in-linking-and-form-submission) -- [Strongly recommended practices](#strongly-recommended-practices) - - [Keep just one association](#keep-just-one-association) - - [Respect cookie and local storage deletions](#respect-cookie-and-local-storage-deletions) - - [Comply with local laws and regulations](#comply-with-local-laws-and-regulations) +- [Background](#background) + - [Display contexts for AMP pages](#display-contexts-for-amp-pages) + - [Multiple contexts means multiple state management](#multiple-contexts-means-multiple-state-management) +- [Implementation guide](#implementation-guide) + - [Before getting started](#before-getting-started) + - [Task 1: For non-AMP pages on the publisher origin, set up an identifier and send analytics pings](#task-1-for-non-amp-pages-on-the-publisher-origin-set-up-an-identifier-and-send-analytics-pings) + - [Task 2: For AMP pages, set up an identifier and send analytics pings by including Client ID replacement in amp-analytics pings](#task-2-for-amp-pages-set-up-an-identifier-and-send-analytics-pings-by-including-client-id-replacement-in-amp-analytics-pings) + - [Task 3: Process analytics pings from pages on the publisher origin](#task-3-process-analytics-pings-from-pages-on-the-publisher-origin) + - [Task 4: Process analytics pings from AMP cache or AMP viewer display contexts and establish identifier mappings (if needed)](#task-4-process-analytics-pings-from-amp-cache-or-amp-viewer-display-contexts-and-establish-identifier-mappings-if-needed) + - [Task 5: Using Client ID in linking and form submission](#task-5-using-client-id-in-linking-and-form-submission) +- [Strongly recommended practices](#strongly-recommended-practices) + - [Keep just one association](#keep-just-one-association) + - [Respect cookie and local storage deletions](#respect-cookie-and-local-storage-deletions) + - [Comply with local laws and regulations](#comply-with-local-laws-and-regulations) User state is an important concept on today’s web. Consider the following use cases that are enabled by managing user state: -- A merchant builds a useful **shopping cart** that shows a user the same items during their second visit that they had added to the cart during their first visit many weeks ago. Such an experience increases the chance of the user buying that item by making sure they remain aware of the item they considered buying in the past. -- A news publisher who can tailor **recommended articles** to a reader based on the reader’s repeated visits to the publisher’s articles, which helps keep the reader engaged and discovering more content. -- A website developer running any type of site collects **analytics** that can tell if two pageviews belong to the same person who saw two pages or to two different people who each saw a single page. Having this insight helps to know how the site is performing, and, ultimately, how to improve it. +- A merchant builds a useful **shopping cart** that shows a user the same items during their second visit that they had added to the cart during their first visit many weeks ago. Such an experience increases the chance of the user buying that item by making sure they remain aware of the item they considered buying in the past. +- A news publisher who can tailor **recommended articles** to a reader based on the reader’s repeated visits to the publisher’s articles, which helps keep the reader engaged and discovering more content. +- A website developer running any type of site collects **analytics** that can tell if two pageviews belong to the same person who saw two pages or to two different people who each saw a single page. Having this insight helps to know how the site is performing, and, ultimately, how to improve it. This article is designed to help you be more successful in **managing non-authenticated user state in AMP**, a way of providing a seamless user journey even if the user hasn’t taken an action to provide their identity, like signing in. After reviewing some of the challenges and considerations in approaching this topic, this guide outlines the ways in which user state is supported by AMP and offers recommendations on how you can approach a technical implementation. @@ -42,9 +42,9 @@ The topic of user state deserves special attention in AMP because AMP pages can You can think of AMP as a portable content format that enables content to be loaded fast anywhere. AMP documents can be displayed via three noteworthy contexts: -- The publisher's origin -- An AMP cache -- An AMP viewer +- The publisher's origin +- An AMP cache +- An AMP viewer @@ -277,8 +277,8 @@ Here (1) and (2) happen on different origins (or contexts). Because of this, the To address the problem of overcounting, you should employ the following strategy, the potency of which depends on whether reading or writing of third-party cookies is permitted: -- **Immediate identifier reconciliation: If you can access or change the publisher origin cookies**, use or create the publisher origin identifier and ignore any identifier within the analytics request. You will be able to successfully link activity between the two contexts. -- **Delayed identifier reconciliation: If you cannot access or change the publisher origin identifier (i.e. the cookies)**, then fall back to the AMP Client ID that comes within the analytics request itself. Use this identifier as an “**alias**”, rather than using or creating a new publisher origin identifier (cookie), which you cannot do (because of third party cookie blocking), and add the alias to a **mapping table**. You will be unsuccessful in immediately linking activity between the two contexts, but by using a mapping table you may be able to link the AMP Client ID value with the publisher origin identifier on a future visit by the user. When this happens, you will have the needed information to link the activity and reconcile that the page visits in the different contexts came from the same user. Task 5 describes how to achieve a complete solution in specific scenarios where the user traverses from one page immediately to another. +- **Immediate identifier reconciliation: If you can access or change the publisher origin cookies**, use or create the publisher origin identifier and ignore any identifier within the analytics request. You will be able to successfully link activity between the two contexts. +- **Delayed identifier reconciliation: If you cannot access or change the publisher origin identifier (i.e. the cookies)**, then fall back to the AMP Client ID that comes within the analytics request itself. Use this identifier as an “**alias**”, rather than using or creating a new publisher origin identifier (cookie), which you cannot do (because of third party cookie blocking), and add the alias to a **mapping table**. You will be unsuccessful in immediately linking activity between the two contexts, but by using a mapping table you may be able to link the AMP Client ID value with the publisher origin identifier on a future visit by the user. When this happens, you will have the needed information to link the activity and reconcile that the page visits in the different contexts came from the same user. Task 5 describes how to achieve a complete solution in specific scenarios where the user traverses from one page immediately to another. #### Implementation steps @@ -286,8 +286,8 @@ On the server check for an existing publisher origin identifier Read the cookies sent as part of the analytics request. In our example, this means checking for the `uid` cookie from example.com. -- If the `uid` value is successfully read, use it to record analytics data (**analytics record identifier**). Because of [Task 1](#task1), we know this identifier’s value is `$publisher_origin_identifier`. With an analytics record identifier established, we can skip ahead to the [Data storage](#data-storage) section. -- If the `uid` value is not successfully read, proceed with the steps below involving the mapping table. +- If the `uid` value is successfully read, use it to record analytics data (**analytics record identifier**). Because of [Task 1](#task1), we know this identifier’s value is `$publisher_origin_identifier`. With an analytics record identifier established, we can skip ahead to the [Data storage](#data-storage) section. +- If the `uid` value is not successfully read, proceed with the steps below involving the mapping table. ##### Mapping table @@ -436,8 +436,8 @@ If the information was exposed just to the server, e.g. via a form POST, then yo If the information is available via URL and you wish to process it, there are a couple of approaches you can use: -- Process during redirect (server-side handling) -- Process on the landing page (client-side handling) +- Process during redirect (server-side handling) +- Process on the landing page (client-side handling) **Process during redirect (server-side handling)** @@ -564,8 +564,8 @@ When you are searching the mapping table, take note of which situation applies a If you cannot locate either identifier value being used in your mapping table, establish a new mapping: -- If the analytics request comes from a page on your publisher origin, then you should choose the value corresponding to `uid` to be the analytics record identifier; choose the value of `orig_uid` to be the “alias”. -- If the analytics request does not come from a page on your publisher origin, then you should choose the value corresponding to `uid` to be an “alias” value in the mapping table. Then, proceed with the remaining instructions in [Task 4](#task4) to create a prospective publisher origin identifier and attempt to set this value as a cookie on the origin. +- If the analytics request comes from a page on your publisher origin, then you should choose the value corresponding to `uid` to be the analytics record identifier; choose the value of `orig_uid` to be the “alias”. +- If the analytics request does not come from a page on your publisher origin, then you should choose the value corresponding to `uid` to be an “alias” value in the mapping table. Then, proceed with the remaining instructions in [Task 4](#task4) to create a prospective publisher origin identifier and attempt to set this value as a cookie on the origin. ##### Parameter validation diff --git a/docs/spec/email/amp-email-components.md b/docs/spec/email/amp-email-components.md index 559a7bf46e4e..d0a89493b657 100644 --- a/docs/spec/email/amp-email-components.md +++ b/docs/spec/email/amp-email-components.md @@ -9,9 +9,9 @@ The following is the list of [AMP components](https://amp.dev/documentation/comp amp markdown-toc --fix --> -- [Dynamic Content](#dynamic-content) -- [Layout](#layout) -- [Media](#media) +- [Dynamic Content](#dynamic-content) +- [Layout](#layout) +- [Media](#media) ## Dynamic Content diff --git a/docs/testing.md b/docs/testing.md index 0cef52308f81..7d3d3e3577a3 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -11,28 +11,28 @@ This document provides details for testing and building your AMP code. amp markdown-toc --fix --> -- [Testing commands](#testing-commands) -- [Manual testing](#manual-testing) - - [Serve Mode](#serve-mode) - - [Examples](#examples) - - [Document proxy](#document-proxy) - - [A4A envelope (/a4a/, /a4a-3p/)](#a4a-envelope-a4a-a4a-3p) - - [In-a-box envelope (/inabox/)](#in-a-box-envelope-inabox) - - [Chrome extension](#chrome-extension) -- [Visual Diff Tests](#-visual-diff-tests) - - [Failing Tests](#failing-tests) - - [Flaky Tests](#flaky-tests) - - [How Are Tests Executed](#how-are-tests-executed) - - [Adding and Modifying Visual Diff Tests](#adding-and-modifying-visual-diff-tests) -- [Isolated Component Testing](#isolated-component-testing) - - [Launching Storybook](#launching-storybook) - - [Writing test scenarios](#writing-test-scenarios) -- [Testing on devices](#testing-on-devices) - - [Testing with ngrok](#testing-with-ngrok) - - [Testing with Firebase](#testing-with-firebase) - - [Testing Ads](#testing-ads) -- [End-to-End Tests](#end-to-end-tests) -- [Performance Testing Node Build Tools](#performance-testing-node-build-tools) +- [Testing commands](#testing-commands) +- [Manual testing](#manual-testing) + - [Serve Mode](#serve-mode) + - [Examples](#examples) + - [Document proxy](#document-proxy) + - [A4A envelope (/a4a/, /a4a-3p/)](#a4a-envelope-a4a-a4a-3p) + - [In-a-box envelope (/inabox/)](#in-a-box-envelope-inabox) + - [Chrome extension](#chrome-extension) +- [Visual Diff Tests](#-visual-diff-tests) + - [Failing Tests](#failing-tests) + - [Flaky Tests](#flaky-tests) + - [How Are Tests Executed](#how-are-tests-executed) + - [Adding and Modifying Visual Diff Tests](#adding-and-modifying-visual-diff-tests) +- [Isolated Component Testing](#isolated-component-testing) + - [Launching Storybook](#launching-storybook) + - [Writing test scenarios](#writing-test-scenarios) +- [Testing on devices](#testing-on-devices) + - [Testing with ngrok](#testing-with-ngrok) + - [Testing with Firebase](#testing-with-firebase) + - [Testing Ads](#testing-ads) +- [End-to-End Tests](#end-to-end-tests) +- [Performance Testing Node Build Tools](#performance-testing-node-build-tools) ## Testing commands @@ -149,11 +149,11 @@ For manual testing build AMP and start the Node.js server by running `amp`. There are 5 serving modes: -- DEFAULT mode serves unminified AMP. Use this during normal development by simply running `amp`. -- MINIFIED mode serves minified AMP. This is closer to what is served in production on the stable channel. Serve this mode by running `amp --minified`. -- CDN mode serves stable channel binaries. Local changes are not served in this mode. Serve CDN mode by running `amp serve --cdn`. -- RTV mode serves the bundle from the given RTV number (a 15 digit number). E.g. `001907161745080`. Serve RTV mode by running `amp serve --rtv ` -- ESM mode serves the esm (module) binaries. First run `amp dist --fortesting --esm` and then serve esm mode by running `amp serve --esm`. _This mode is new, and under active development._ +- DEFAULT mode serves unminified AMP. Use this during normal development by simply running `amp`. +- MINIFIED mode serves minified AMP. This is closer to what is served in production on the stable channel. Serve this mode by running `amp --minified`. +- CDN mode serves stable channel binaries. Local changes are not served in this mode. Serve CDN mode by running `amp serve --cdn`. +- RTV mode serves the bundle from the given RTV number (a 15 digit number). E.g. `001907161745080`. Serve RTV mode by running `amp serve --rtv ` +- ESM mode serves the esm (module) binaries. First run `amp dist --fortesting --esm` and then serve esm mode by running `amp serve --esm`. _This mode is new, and under active development._ To switch serving mode during runtime, go to http://localhost:8000/serve_mode=MODE and set `MODE` to one of the following values: `default`, `compiled`, `cdn` or ``. @@ -191,8 +191,8 @@ A4A can be run either of these two modes: The following forms are supported: -- local document: http://localhost:8000/a4a[-3p]/examples/animations.amp.html -- proxied document with local sources: http://localhost:8000/a4a[-3p]/proxy/output.jsbin.com/pegizoq/quiet +- local document: http://localhost:8000/a4a[-3p]/examples/animations.amp.html +- proxied document with local sources: http://localhost:8000/a4a[-3p]/proxy/output.jsbin.com/pegizoq/quiet When accessing minified JS make sure you run `amp dist` with the `--fortesting` flag so that we do not strip out the localhost code paths. (We do some @@ -205,9 +205,9 @@ Notice that all documents are assumed to have a "fake" signature. Thus, this fun Additionally, the following query parameters can be provided: -- `width` - the width of the `amp-ad` (default "300") -- `height` - the height of the `amp-ad` (default "250") -- `offset` - the offset to push the `amp-ad` down the page (default "0px"). Can be used to push the Ad out of the viewport, e.g. using `offset=150vh`. +- `width` - the width of the `amp-ad` (default "300") +- `height` - the height of the `amp-ad` (default "250") +- `offset` - the offset to push the `amp-ad` down the page (default "0px"). Can be used to push the Ad out of the viewport, e.g. using `offset=150vh`. ### In-a-box envelope (/inabox/) @@ -215,14 +215,14 @@ If you are working on AMP In-a-box Ads, you can use the local in-a-box envelope The following forms are supported: -- local document: http://localhost:8000/inabox/examples/animations.amp.html -- proxied document with local sources: http://localhost:8000/inabox/proxy/output.jsbin.com/pegizoq/quiet +- local document: http://localhost:8000/inabox/examples/animations.amp.html +- proxied document with local sources: http://localhost:8000/inabox/proxy/output.jsbin.com/pegizoq/quiet Additionally, the following query parameters can be provided: -- `width` - the width of the `iframe` (default "300") -- `height` - the height of the `iframe` (default "250") -- `offset` - the offset to push the `iframe` down the page (default "0px"). Can be used to push the Ad out of the viewport, e.g. using `offset=150vh`. +- `width` - the width of the `iframe` (default "300") +- `height` - the height of the `iframe` (default "250") +- `offset` - the offset to push the `iframe` down the page (default "0px"). Can be used to push the Ad out of the viewport, e.g. using `offset=150vh`. ### Chrome extension @@ -234,10 +234,10 @@ In addition to building the AMP runtime and running `amp [unit|integration]`, th The technology stack used is: -- [Percy](https://percy.io/), a visual regression testing service for webpages -- [Puppeteer](https://developers.google.com/web/tools/puppeteer/), a driver capable of loading webpages for diffing -- [Percy-Puppeteer](https://github.com/percy/percy-puppeteer), a framework that integrates Puppeteer with Percy -- [Headless Chrome](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md), the Chrome/Chromium browser in headless mode +- [Percy](https://percy.io/), a visual regression testing service for webpages +- [Puppeteer](https://developers.google.com/web/tools/puppeteer/), a driver capable of loading webpages for diffing +- [Percy-Puppeteer](https://github.com/percy/percy-puppeteer), a framework that integrates Puppeteer with Percy +- [Headless Chrome](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md), the Chrome/Chromium browser in headless mode The [`ampproject/amphtml`](https://github.com/ampproject/amphtml) repository on GitHub is linked to the [Percy project](https://percy.io/ampproject/amphtml) of the same name. You will see a check called `percy/amphtml` on your PR. If your PR results in visual diff(s), clicking on the `details` link will show you the snapshots with the diffs highlighted. @@ -253,12 +253,12 @@ If a Percy test flakes and you would like to trigger a rerun, you can't do that Visual diff tests are defined in the [`visual-tests.jsonc`](../test/visual-diff/visual-tests.jsonc), see file for the configurations of each test. When running, the visual diff test runner does the following for each test case: -- Navgates to the defined page using a headless Chrome browser -- Waits for the page to finish loading, both by verifying idle network connections and lack of loader animations -- If defined, waits until the appropriate CSS selectors appear/disappear from the page -- If defined, waits an arbitrary amount of time (e.g., for components that have time-delayed mutations) -- If defined, executes any custom interaction test code -- Uploads a snapshot of the page's DOM (converted to an HTML string) to the Percy service +- Navgates to the defined page using a headless Chrome browser +- Waits for the page to finish loading, both by verifying idle network connections and lack of loader animations +- If defined, waits until the appropriate CSS selectors appear/disappear from the page +- If defined, waits an arbitrary amount of time (e.g., for components that have time-delayed mutations) +- If defined, executes any custom interaction test code +- Uploads a snapshot of the page's DOM (converted to an HTML string) to the Percy service When all snapshots finish uploading, Percy will process the visual diffs and report back to GitHub as a pull request status. Percy renders the snapshots in their own browsers and take a screenshot. If the new screenshot differs from the previously approved screenshot you will get a visual highlighting of where that difference lies. @@ -286,13 +286,13 @@ amp storybook You may launch a specific environment by providing `--storybook_env`: -- **`preact`** +- **`preact`** ```sh amp storybook --storybook_env=preact ``` -- **`react`** +- **`react`** ```sh amp storybook --storybook_env=react @@ -300,7 +300,7 @@ You may launch a specific environment by providing `--storybook_env`: > Launching the **`react`** environment requires component bundles. You should ensure that they're present in `extensions/**/dist` directories beforehand, by running `amp build --extensions=...` for all Bento components. -- **`amp`** +- **`amp`** ```sh amp storybook --storybook_env=amp @@ -312,13 +312,13 @@ You may launch a specific environment by providing `--storybook_env`: Test scenarios (stories) are located inside a component's directory. Their filename suffix determines whether they run on the `amp` environment, or on the `preact` and `react` environments: -- **`preact`** Stories end with `.js`: +- **`preact`** Stories end with `.js`: `extensions/amp-example/0.1/storybook/Basic.js` -- **`react`** Stories use the same files as **`preact`**. +- **`react`** Stories use the same files as **`preact`**. -- **`amp`** Stories end with `.amp.js`: +- **`amp`** Stories end with `.amp.js`: `extensions/amp-example/0.1/storybook/Basic.amp.js` @@ -348,13 +348,13 @@ amp firebase firebase deploy ``` -- When initializing firebase within the directory via `firebase init`, make sure to select the following options when asked: +- When initializing firebase within the directory via `firebase init`, make sure to select the following options when asked: -* "Which Firebase CLI features do you want to setup for this folder?" select `Hosting: Configure and deploy Firebase Hosting sites`. -* "What do you want to use as your public directory?" enter `firebase`. -* "Select a default Firebase project for this directory:" select your project name if it's already created, otherwise choose `[don't setup a new project]` and add one later. - - Note: If you haven't already, you will have to create a project via the [Firebase Console](https://console.firebase.google.com) after you are done initializing and before you deploy. Once you create the project, you can make it active in your CLI with `firebase use your-project-name` or give it an alias by selecting your project after running `firebase use --add`. -* "Configure as a single-page app (rewrite all urls to /index.html)?" select `n`. +* "Which Firebase CLI features do you want to setup for this folder?" select `Hosting: Configure and deploy Firebase Hosting sites`. +* "What do you want to use as your public directory?" enter `firebase`. +* "Select a default Firebase project for this directory:" select your project name if it's already created, otherwise choose `[don't setup a new project]` and add one later. + - Note: If you haven't already, you will have to create a project via the [Firebase Console](https://console.firebase.google.com) after you are done initializing and before you deploy. Once you create the project, you can make it active in your CLI with `firebase use your-project-name` or give it an alias by selecting your project after running `firebase use --add`. +* "Configure as a single-page app (rewrite all urls to /index.html)?" select `n`. `amp firebase` will generate a `firebase` folder and copy over all files from `dist`, `examples` and `test/manual`. It will rewrite all urls in the copied files to point to the local versions of AMP (i.e. the ones copied from `dist` to `firebase/dist`). When you initialize firebase, you should set the `firebase` `public` directory to `firebase`. This way `firebase deploy` will just directly copy and deploy the contents of the generated `firebase` folder. As an example, your `firebase.json` file can look something like this: diff --git a/docs/writing-css.md b/docs/writing-css.md index ce392dbf1ac7..0342a18ce677 100644 --- a/docs/writing-css.md +++ b/docs/writing-css.md @@ -7,19 +7,19 @@ amp markdown-toc --fix --> -- [Who should read this doc?](#who-should-read-this-doc) -- [What is Specificity?](#what-is-specificity) - - [Example: CSS selectors](#example-css-selectors) - - [How to calculate Specificity](#how-to-calculate-specificity) -- [Writing CSS in AMP Runtime or Extensions](#writing-css-in-amp-runtime-or-extensions) - - [Creating a new Selector](#creating-a-new-selector) - - [Modifying an existing Selector](#modifying-an-existing-selector) - - [FOUC](#fouc) - - [Rule of thumb](#rule-of-thumb) -- [Case Studies](#case-studies) - - [AMP Selector CSS has high specificity](#amp-selector-css-has-high-specificity) - - [AMP Accordion CSS changes broke specificity](#amp-accordion-css-changes-broke-specificity) -- [Reading material](#reading-material) +- [Who should read this doc?](#who-should-read-this-doc) +- [What is Specificity?](#what-is-specificity) + - [Example: CSS selectors](#example-css-selectors) + - [How to calculate Specificity](#how-to-calculate-specificity) +- [Writing CSS in AMP Runtime or Extensions](#writing-css-in-amp-runtime-or-extensions) + - [Creating a new Selector](#creating-a-new-selector) + - [Modifying an existing Selector](#modifying-an-existing-selector) + - [FOUC](#fouc) + - [Rule of thumb](#rule-of-thumb) +- [Case Studies](#case-studies) + - [AMP Selector CSS has high specificity](#amp-selector-css-has-high-specificity) + - [AMP Accordion CSS changes broke specificity](#amp-accordion-css-changes-broke-specificity) +- [Reading material](#reading-material) ## Who should read this doc? @@ -183,9 +183,9 @@ Fixing PR: https://github.com/ampproject/amphtml/commit/e12deb125bc0bed16d33481e +} ``` -- Breaking change: https://github.com/ampproject/amphtml/commit/f2a361651b4b4d1d484c6cd9502c895695545d -- GH Issue : https://github.com/ampproject/amphtml/issues/10224 -- Partial Rollback: https://github.com/ampproject/amphtml/pull/10225 +- Breaking change: https://github.com/ampproject/amphtml/commit/f2a361651b4b4d1d484c6cd9502c895695545d +- GH Issue : https://github.com/ampproject/amphtml/issues/10224 +- Partial Rollback: https://github.com/ampproject/amphtml/pull/10225 The lesson learnt here is that even though the breaking CSS was a good change (it fixed the FOUC due to the class introduced at BUILD), it moved properties from a selector with LOWER @@ -193,6 +193,6 @@ specificity to HIGHER specificity, which breaks backward compatibility. ## Reading material -- https://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/ -- https://csswizardry.com/2012/05/keep-your-css-selectors-short/ -- https://philipwalton.com/articles/do-we-actually-need-specificity-in-css/ +- https://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/ +- https://csswizardry.com/2012/05/keep-your-css-selectors-short/ +- https://philipwalton.com/articles/do-we-actually-need-specificity-in-css/ diff --git a/extensions/amp-story/1.0/amp-story.js b/extensions/amp-story/1.0/amp-story.js index ccdff08c808e..1d07a90f9ba7 100644 --- a/extensions/amp-story/1.0/amp-story.js +++ b/extensions/amp-story/1.0/amp-story.js @@ -2694,9 +2694,9 @@ export class AmpStory extends AMP.BaseElement { } return Boolean( win.CSS && - win.CSS.supports && - win.CSS.supports('display', 'grid') && - win.CSS.supports('color', 'var(--test)') + win.CSS.supports && + win.CSS.supports('display', 'grid') && + win.CSS.supports('color', 'var(--test)') ); } diff --git a/package-lock.json b/package-lock.json index 5ea31879a55b..28f04baa7ceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -97,17 +97,17 @@ "esbuild": "0.27.1", "escodegen": "2.1.0", "eslint": "8.57.1", - "eslint-config-prettier": "9.1.0", + "eslint-config-prettier": "9.1.2", "eslint-import-resolver-babel-module": "5.3.2", "eslint-plugin-chai-expect": "3.1.0", "eslint-plugin-eslint-plugin": "5.5.1", - "eslint-plugin-import": "2.31.0", + "eslint-plugin-import": "2.32.0", "eslint-plugin-jasmine": "4.2.2", "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-local": "4.2.2", "eslint-plugin-module-resolver": "1.5.0", - "eslint-plugin-prettier": "5.2.1", - "eslint-plugin-react": "7.37.1", + "eslint-plugin-prettier": "5.5.4", + "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-sort-destructure-keys": "1.6.0", "esprima": "4.0.1", @@ -161,7 +161,7 @@ "postcss": "8.4.39", "postcss-import": "16.1.0", "posthtml": "0.16.6", - "prettier": "3.3.3", + "prettier": "3.7.4", "react": "17.0.2", "react-dom": "17.0.2", "rocambole": "0.7.0", @@ -7371,13 +7371,14 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -7406,17 +7407,20 @@ "dev": true }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7454,17 +7458,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7474,15 +7480,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7492,15 +7499,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7526,19 +7534,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -7611,6 +7619,16 @@ "dev": true, "license": "MIT" }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/async-sema": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", @@ -8667,16 +8685,47 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -9780,14 +9829,15 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -9797,29 +9847,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -10217,6 +10269,21 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "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==", + "dev": true, + "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/duplexer": { "version": "0.1.2", "dev": true, @@ -10416,57 +10483,66 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -10476,13 +10552,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -10497,25 +10571,28 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -10528,10 +10605,11 @@ "dev": true }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "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==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -10540,36 +10618,44 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -10731,10 +10817,11 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "dev": true, + "license": "MIT", "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -10780,10 +10867,11 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -10834,29 +10922,30 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, + "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -10871,6 +10960,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -10880,6 +10970,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -10892,6 +10983,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10904,6 +10996,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -11089,13 +11182,14 @@ "dev": true }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -11106,7 +11200,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -11118,29 +11212,59 @@ } } }, + "node_modules/eslint-plugin-prettier/node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/eslint-plugin-prettier/node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/eslint-plugin-react": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", - "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", + "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", + "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -11167,6 +11291,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -11179,6 +11304,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -11191,6 +11317,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -11208,6 +11335,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -12452,12 +12580,19 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/for-in": { @@ -12596,15 +12731,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -12680,16 +12818,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "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", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "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" @@ -12714,6 +12858,20 @@ "node": ">=4" } }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -12727,14 +12885,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -12815,12 +12974,14 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -12855,12 +13016,13 @@ "integrity": "sha512-h2lBEX2tjWwfR+dhFukGER15vKY+4cA3nRqwKSOsBdyizlOxTAHOWbEYiGnMoom3/SrVeQ5uG0eKsbxQ3wbsxA==" }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13114,10 +13276,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -13126,10 +13292,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -13455,14 +13622,15 @@ "license": "ISC" }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -13536,13 +13704,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -13558,12 +13728,17 @@ "dev": true }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -13573,12 +13748,16 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13596,13 +13775,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13640,10 +13820,11 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -13655,11 +13836,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -13670,12 +13854,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13715,12 +13901,16 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13786,10 +13976,14 @@ "license": "ISC" }, "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13815,9 +14009,15 @@ } }, "node_modules/is-number-object": { - "version": "1.0.4", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -13871,13 +14071,16 @@ "license": "MIT" }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -13902,21 +14105,26 @@ } }, "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -13937,12 +14145,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13957,11 +14167,15 @@ "license": "MIT" }, "node_modules/is-symbol": { - "version": "1.0.3", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.1" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -13971,12 +14185,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -13997,34 +14212,46 @@ } }, "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14420,16 +14647,21 @@ "license": "MIT" }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jest-changed-files": { @@ -18619,6 +18851,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/math-random": { "version": "1.0.4", "dev": true, @@ -19574,10 +19816,14 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -19606,14 +19852,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -19624,14 +19873,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -19681,12 +19932,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -19772,6 +20025,24 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "2.3.0", "dev": true, @@ -20750,10 +21021,11 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, + "license": "MIT", "peer": true, "bin": { "prettier": "bin/prettier.cjs" @@ -21203,18 +21475,20 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -21252,15 +21526,18 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -21527,14 +21804,16 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -21559,15 +21838,40 @@ "version": "1.0.1", "dev": true }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -21816,17 +22120,18 @@ "dev": true }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -21859,6 +22164,21 @@ "node": ">=0.10.0" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -21889,15 +22209,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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" @@ -22238,6 +22616,20 @@ "node": ">= 0.6" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-browserify": { "version": "3.0.0", "dev": true, @@ -22355,23 +22747,25 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -22391,15 +22785,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -22409,15 +22807,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -23212,30 +23615,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -23245,17 +23650,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -23265,17 +23672,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -23354,15 +23762,19 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -23722,39 +24134,45 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -23767,33 +24185,41 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { diff --git a/package.json b/package.json index ac06fafbf663..2c6e39ab6c1d 100644 --- a/package.json +++ b/package.json @@ -102,17 +102,17 @@ "esbuild": "0.27.1", "escodegen": "2.1.0", "eslint": "8.57.1", - "eslint-config-prettier": "9.1.0", + "eslint-config-prettier": "9.1.2", "eslint-import-resolver-babel-module": "5.3.2", "eslint-plugin-chai-expect": "3.1.0", "eslint-plugin-eslint-plugin": "5.5.1", - "eslint-plugin-import": "2.31.0", + "eslint-plugin-import": "2.32.0", "eslint-plugin-jasmine": "4.2.2", "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-local": "4.2.2", "eslint-plugin-module-resolver": "1.5.0", - "eslint-plugin-prettier": "5.2.1", - "eslint-plugin-react": "7.37.1", + "eslint-plugin-prettier": "5.5.4", + "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-sort-destructure-keys": "1.6.0", "esprima": "4.0.1", @@ -166,7 +166,7 @@ "postcss": "8.4.39", "postcss-import": "16.1.0", "posthtml": "0.16.6", - "prettier": "3.3.3", + "prettier": "3.7.4", "react": "17.0.2", "react-dom": "17.0.2", "rocambole": "0.7.0", diff --git a/src/amp-story-player/README.md b/src/amp-story-player/README.md index 7947f49c97d8..f6f74aaaa6a6 100644 --- a/src/amp-story-player/README.md +++ b/src/amp-story-player/README.md @@ -23,23 +23,23 @@ This update contains guidance on using the Web Story Player to support: -- [Summary](#summary) -- [Player setup](#player-setup) -- [Navigating between stories](#navigating-between-stories) -- [Integrating web stories into your website (entrypoints)](#integrating-web-stories-into-your-website-entrypoints) -- [Programmatically fetching more stories](#programmatically-fetching-more-stories) -- [Circular Wrapping](#circular-wrapping) -- [Customizing position & visibility of story UI controls](#customizing-position--visibility-of-story-ui-controls) -- [Custom Events](#custom-events) -- [Upcoming API Change: Poster Image](#upcoming-api-change-poster-image) -- [Additional use case demos](#additional-use-case-demos) -- [FAQs (please feel free to reach out with other questions & thoughts)](#faqs-please-feel-free-to-reach-out-with-other-questions--thoughts) +- [Summary](#summary) +- [Player setup](#player-setup) +- [Navigating between stories](#navigating-between-stories) +- [Integrating web stories into your website (entrypoints)](#integrating-web-stories-into-your-website-entrypoints) +- [Programmatically fetching more stories](#programmatically-fetching-more-stories) +- [Circular Wrapping](#circular-wrapping) +- [Customizing position & visibility of story UI controls](#customizing-position--visibility-of-story-ui-controls) +- [Custom Events](#custom-events) +- [Upcoming API Change: Poster Image](#upcoming-api-change-poster-image) +- [Additional use case demos](#additional-use-case-demos) +- [FAQs (please feel free to reach out with other questions & thoughts)](#faqs-please-feel-free-to-reach-out-with-other-questions--thoughts) Beyond this, you’ll also find: -- [Additional use case demos](#Additional-use-case-demos) -- [Additional explorations and roadmap](#Additional-explorations-and-roadmap) -- [FAQs](#faqs-please-feel-free-to-reach-out-with-other-questions--thoughts) +- [Additional use case demos](#Additional-use-case-demos) +- [Additional explorations and roadmap](#Additional-explorations-and-roadmap) +- [FAQs](#faqs-please-feel-free-to-reach-out-with-other-questions--thoughts) ## Player setup @@ -245,17 +245,17 @@ The configuration will end up looking like the following: Specify a control object with the “close” name to get the close icon. -- `event`: The close button dispatches the `amp-story-player-close` event. +- `event`: The close button dispatches the `amp-story-player-close` event. The “close” control supports the following customizable properties: -- `position`: “start” or “end”. - - Places the icon either on the left or right on LTR languages. -- `visibility`: “hidden” or “visible” (default). - - Toggles the control’s visibility. If omitted, the default is visible. - - See [Example #2 - Showing skip-to-next story on desktop.](#Example-#2---Showing-skip-to-next-story-on-desktop) -- `backgroundImageUrl`: string with url or data string (escaped). - - Changes the icon image to the provided url or data string (for inline svgs). +- `position`: “start” or “end”. + - Places the icon either on the left or right on LTR languages. +- `visibility`: “hidden” or “visible” (default). + - Toggles the control’s visibility. If omitted, the default is visible. + - See [Example #2 - Showing skip-to-next story on desktop.](#Example-#2---Showing-skip-to-next-story-on-desktop) +- `backgroundImageUrl`: string with url or data string (escaped). + - Changes the icon image to the provided url or data string (for inline svgs). ### Skip-to-next @@ -263,18 +263,18 @@ Skips to the next story inside the player (only available on desktop). The “skip-to-next” control supports the following customizable properties: -- `position`: “start” or “end”. - - Places the icon either on the left or right on LTR languages. -- `visibility`: “hidden” or “visible” (default). - - Toggles the control’s visibility. If omitted, the default is visible. -- `backgroundImageUrl`: string with url or data string (escaped). - - Changes the icon image to the provided url or data string (for inline svgs). +- `position`: “start” or “end”. + - Places the icon either on the left or right on LTR languages. +- `visibility`: “hidden” or “visible” (default). + - Toggles the control’s visibility. If omitted, the default is visible. +- `backgroundImageUrl`: string with url or data string (escaped). + - Changes the icon image to the provided url or data string (for inline svgs). ### Custom control You can add a custom control to the stories inside the player with a custom control. Simply specify a “name” and an “backgroundImageUrl”, and any optional properties: -- `name` (**required**): a string with the name of the control. e.g. “lightbox”. **The dispatched event will depend on this name.** The custom event will be the name of the control prefixed with `amp-story-player-*`. E.g. `amp-story-player-lightbox`: +- `name` (**required**): a string with the name of the control. e.g. “lightbox”. **The dispatched event will depend on this name.** The custom event will be the name of the control prefixed with `amp-story-player-*`. E.g. `amp-story-player-lightbox`: ```javascript const player = document.body.querySelector("amp-story-player"); @@ -286,12 +286,12 @@ player.addEventListener("amp-story-player-lightbox", () => { }); ``` -- `backgroundImageUrl` (**required**): Accepts URLs, as well as svgs and `data` paths (note that strings must be JSON escaped). See [example 3](#Example-#3---Changing-the-icon-of-the-close-button). - - Changes the control icon. -- `position`: “start” or “end”. - - Places the icon either on the left or right on LTR languages. -- `visibility`: “hidden” or “visible” (default). - - Toggles the control’s visibility. If omitted, the default is visible. +- `backgroundImageUrl` (**required**): Accepts URLs, as well as svgs and `data` paths (note that strings must be JSON escaped). See [example 3](#Example-#3---Changing-the-icon-of-the-close-button). + - Changes the control icon. +- `position`: “start” or “end”. + - Places the icon either on the left or right on LTR languages. +- `visibility`: “hidden” or “visible” (default). + - Toggles the control’s visibility. If omitted, the default is visible. ### Example #1 - Close button on the start position @@ -432,10 +432,10 @@ This new API is still a work in progress, and will send more information when it Good question. While the basic functionality of the player is in the [AMP version](https://amp.dev/documentation/components/amp-story-player/), including embedding multiple stories and swiping through them, we are still working on porting over some of the features from the non-AMP version to the AMP version. These include: -- Circular wrapping -- Programmatically fetching more stories from an endpoint -- Customizable UI controls -- Custom events +- Circular wrapping +- Programmatically fetching more stories from an endpoint +- Customizable UI controls +- Custom events ### Is the player ready to use? When will these features be ready?